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.

2542 lines
52 KiB

  1. /*++
  2. Copyright (c) 1996-2002 Microsoft Corporation
  3. Module Name:
  4. straddr.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Routines to string to\from address conversions.
  8. Author:
  9. Jim Gilroy (jamesg) December 1996
  10. Revision History:
  11. jamesg June 2000 New IP6 parsing.
  12. jamesg Oct 2000 Created this module.
  13. --*/
  14. #include "local.h"
  15. #include "ws2tcpip.h" // IP6 inaddr definitions
  16. //
  17. // String to address
  18. //
  19. BOOL
  20. Dns_Ip6StringToAddress_A(
  21. OUT PIP6_ADDRESS pIp6Addr,
  22. IN PCSTR pString
  23. )
  24. /*++
  25. Routine Description:
  26. Convert string to IP6 address.
  27. Arguments:
  28. pAddress -- ptr to IP6 address to be filled in
  29. pString -- string with IP6 address
  30. Return Value:
  31. TRUE if successful.
  32. FALSE otherwise.
  33. --*/
  34. {
  35. DNS_STATUS status;
  36. PCHAR pstringEnd = NULL;
  37. DNSDBG( PARSE2, (
  38. "Dns_Ip6StringToAddress_A( %s )\n",
  39. pString ));
  40. //
  41. // convert to IP6 address
  42. //
  43. status = RtlIpv6StringToAddressA(
  44. pString,
  45. & pstringEnd,
  46. (PIN6_ADDR) pIp6Addr );
  47. return( status == NO_ERROR && *pstringEnd==0 );
  48. }
  49. BOOL
  50. Dns_Ip6StringToAddressEx_A(
  51. OUT PIP6_ADDRESS pIp6Addr,
  52. IN PCSTR pchString,
  53. IN DWORD dwStringLength
  54. )
  55. /*++
  56. Routine Description:
  57. Convert string to IP6 address.
  58. This version handles non-NULL-terminated strings
  59. for DNS server file load.
  60. Arguments:
  61. pAddress -- ptr to IP6 address to be filled in
  62. pchString -- string with IP6 address
  63. dwStringLength -- string length
  64. Return Value:
  65. TRUE if successful.
  66. FALSE otherwise.
  67. --*/
  68. {
  69. CHAR tempBuf[ IP6_ADDRESS_STRING_BUFFER_LENGTH ];
  70. PCSTR pstring;
  71. DNSDBG( PARSE2, (
  72. "Dns_Ip6StringToAddressEx_A( %.*s )\n"
  73. "\tpchString = %p\n",
  74. dwStringLength,
  75. pchString,
  76. pchString ));
  77. //
  78. // copy string if given length
  79. // if no length assume NULL terminated
  80. //
  81. pstring = pchString;
  82. if ( dwStringLength )
  83. {
  84. DWORD bufLength = IP6_ADDRESS_STRING_BUFFER_LENGTH;
  85. if ( ! Dns_StringCopy(
  86. tempBuf,
  87. & bufLength,
  88. (PCHAR) pstring,
  89. dwStringLength,
  90. DnsCharSetAnsi,
  91. DnsCharSetAnsi ) )
  92. {
  93. return( FALSE );
  94. }
  95. pstring = tempBuf;
  96. }
  97. // convert to IP6 address
  98. return Dns_Ip6StringToAddress_A(
  99. pIp6Addr,
  100. pstring );
  101. }
  102. BOOL
  103. Dns_Ip6StringToAddress_W(
  104. OUT PIP6_ADDRESS pIp6Addr,
  105. IN PCWSTR pwString
  106. )
  107. /*++
  108. Routine Description:
  109. Build IP6 address from wide string.
  110. Arguments:
  111. pwString -- unicode IP6 string
  112. pIp6Addr -- addr to recv IP6 address
  113. Return Value:
  114. TRUE if successful conversion.
  115. FALSE on bad string.
  116. --*/
  117. {
  118. DNS_STATUS status;
  119. PWCHAR pstringEnd = NULL;
  120. DNSDBG( PARSE2, (
  121. "Dns_Ip6StringToAddress_W( %S )\n",
  122. pwString ));
  123. //
  124. // convert to IP6 address
  125. //
  126. status = RtlIpv6StringToAddressW(
  127. pwString,
  128. & pstringEnd,
  129. (PIN6_ADDR) pIp6Addr );
  130. return( status == NO_ERROR && *pstringEnd==0 );
  131. }
  132. BOOL
  133. Dns_Ip4StringToAddress_A(
  134. OUT PIP4_ADDRESS pIp4Addr,
  135. IN PCSTR pString
  136. )
  137. /*++
  138. Routine Description:
  139. Build IP4 address from narrow string.
  140. Arguments:
  141. pIp4Addr -- addr to recv IP6 address
  142. pString -- unicode IP4 string
  143. Return Value:
  144. TRUE if successful conversion.
  145. FALSE on bad string.
  146. --*/
  147. {
  148. IP4_ADDRESS ip;
  149. // if inet_addr() returns error, verify then error out
  150. ip = inet_addr( pString );
  151. if ( ip == INADDR_BROADCAST &&
  152. strcmp( pString, "255.255.255.255" ) != 0 )
  153. {
  154. return( FALSE );
  155. }
  156. *pIp4Addr = ip;
  157. return( TRUE );
  158. }
  159. BOOL
  160. Dns_Ip4StringToAddressEx_A(
  161. OUT PIP4_ADDRESS pIp4Addr,
  162. IN PCSTR pchString,
  163. IN DWORD dwStringLength
  164. )
  165. /*++
  166. Routine Description:
  167. Build IP4 address from narrow string.
  168. This version handles non-NULL terminated strings
  169. Arguments:
  170. pIp4Addr -- addr to recv IP6 address
  171. pString -- unicode IP4 string
  172. dwStringLength -- string length; 0 if NULL terminated
  173. Return Value:
  174. TRUE if successful conversion.
  175. FALSE on bad string.
  176. --*/
  177. {
  178. CHAR tempBuf[ IP4_ADDRESS_STRING_BUFFER_LENGTH ];
  179. PCSTR pstring;
  180. DNSDBG( PARSE2, (
  181. "Dns_Ip4StringToAddressEx_A( %.*s )\n"
  182. "\tpchString = %p\n",
  183. dwStringLength,
  184. pchString,
  185. pchString ));
  186. //
  187. // copy string if given length
  188. // if no length assume NULL terminated
  189. //
  190. pstring = pchString;
  191. if ( dwStringLength )
  192. {
  193. DWORD bufLength = IP4_ADDRESS_STRING_BUFFER_LENGTH;
  194. if ( ! Dns_StringCopy(
  195. tempBuf,
  196. & bufLength,
  197. (PCHAR) pstring,
  198. dwStringLength,
  199. DnsCharSetAnsi,
  200. DnsCharSetAnsi ) )
  201. {
  202. return( FALSE );
  203. }
  204. pstring = tempBuf;
  205. }
  206. return Dns_Ip4StringToAddress_A(
  207. pIp4Addr,
  208. pstring );
  209. }
  210. BOOL
  211. Dns_Ip4StringToAddress_W(
  212. OUT PIP4_ADDRESS pIp4Addr,
  213. IN PCWSTR pwString
  214. )
  215. /*++
  216. Routine Description:
  217. Build IP4 address from wide string.
  218. Arguments:
  219. pIp4Addr -- addr to recv IP6 address
  220. pwString -- unicode IP6 string
  221. Return Value:
  222. TRUE if successful conversion.
  223. FALSE on bad string.
  224. --*/
  225. {
  226. CHAR bufAddr[ IP4_ADDRESS_STRING_BUFFER_LENGTH ];
  227. DWORD bufLength = IP4_ADDRESS_STRING_BUFFER_LENGTH;
  228. // convert to narrow string
  229. // - UTF8 quicker and just fine for numeric
  230. if ( ! Dns_StringCopy(
  231. bufAddr,
  232. & bufLength,
  233. (PCHAR) pwString,
  234. 0, // length unknown
  235. DnsCharSetUnicode,
  236. DnsCharSetUtf8
  237. ) )
  238. {
  239. return( FALSE );
  240. }
  241. return Dns_Ip4StringToAddress_A(
  242. pIp4Addr,
  243. bufAddr );
  244. }
  245. //
  246. // Combined IP4/IP6 string-to-address
  247. //
  248. BOOL
  249. Dns_StringToDnsAddr_W(
  250. OUT PDNS_ADDR pAddr,
  251. IN PCWSTR pString
  252. )
  253. /*++
  254. Routine Description:
  255. Build address (IP4 or IP6) from reverse lookup name.
  256. Arguments:
  257. pAddr -- DNS_ADDR to receive address
  258. pString -- address string
  259. Return Value:
  260. TRUE if successful.
  261. FALSE on error. GetLastError() for status.
  262. --*/
  263. {
  264. return Dns_StringToDnsAddrEx(
  265. pAddr,
  266. (PCSTR) pString,
  267. 0, // any family
  268. TRUE, // unicode
  269. FALSE // forward
  270. );
  271. }
  272. BOOL
  273. Dns_StringToDnsAddr_A(
  274. OUT PDNS_ADDR pAddr,
  275. IN PCSTR pString
  276. )
  277. {
  278. return Dns_StringToDnsAddrEx(
  279. pAddr,
  280. pString,
  281. 0, // any family
  282. FALSE, // not unicode
  283. FALSE // forward
  284. );
  285. }
  286. BOOL
  287. Dns_StringToAddress_W(
  288. OUT PCHAR pAddrBuf,
  289. IN OUT PDWORD pBufLength,
  290. IN PCWSTR pString,
  291. IN OUT PDWORD pAddrFamily
  292. )
  293. /*++
  294. Routine Description:
  295. Build address (IP4 or IP6) from address string.
  296. Arguments:
  297. pAddrBuf -- buffer to receive address
  298. pBufLength -- ptr to address length
  299. input - length of buffer
  300. output - length of address found
  301. pString -- address string
  302. pAddrFamily -- ptr to address family
  303. input - zero for any family or particular family to check
  304. output - family found; zero if no conversion
  305. Return Value:
  306. TRUE if successful.
  307. FALSE on error. GetLastError() for status.
  308. --*/
  309. {
  310. return Dns_StringToAddressEx(
  311. pAddrBuf,
  312. pBufLength,
  313. (PCSTR) pString,
  314. pAddrFamily,
  315. TRUE, // unicode
  316. FALSE // forward
  317. );
  318. }
  319. BOOL
  320. Dns_StringToAddress_A(
  321. OUT PCHAR pAddrBuf,
  322. IN OUT PDWORD pBufLength,
  323. IN PCSTR pString,
  324. IN OUT PDWORD pAddrFamily
  325. )
  326. {
  327. return Dns_StringToAddressEx(
  328. pAddrBuf,
  329. pBufLength,
  330. pString,
  331. pAddrFamily,
  332. FALSE, // ANSI
  333. FALSE // forward
  334. );
  335. }
  336. //
  337. // Address to string
  338. //
  339. PWCHAR
  340. Dns_Ip6AddressToString_W(
  341. OUT PWCHAR pwString,
  342. IN PIP6_ADDRESS pIp6Addr
  343. )
  344. /*++
  345. Routine Description:
  346. Convert IP6 address to string format.
  347. Arguments:
  348. pwString -- buffer to hold string; MUST be at least
  349. IPV6_ADDRESS_STRING_LENGTH+1 in length
  350. pAddress -- IP6 address to convert to string
  351. Return Value:
  352. Ptr to next location in buffer (the terminating NULL).
  353. --*/
  354. {
  355. // DCR: could be macro
  356. return RtlIpv6AddressToStringW(
  357. (PIN6_ADDR) pIp6Addr,
  358. pwString );
  359. }
  360. PCHAR
  361. Dns_Ip6AddressToString_A(
  362. OUT PCHAR pchString,
  363. IN PIP6_ADDRESS pIp6Addr
  364. )
  365. /*++
  366. Routine Description:
  367. Convert IP6 address to string format.
  368. Arguments:
  369. pchString -- buffer to hold string; MUST be at least
  370. IPV6_ADDRESS_STRING_LENGTH+1 in length
  371. pAddress -- IP6 address to convert to string
  372. Return Value:
  373. Ptr to next location in buffer (the terminating NULL).
  374. --*/
  375. {
  376. // DCR: could be macro
  377. return RtlIpv6AddressToStringA(
  378. (PIN6_ADDR) pIp6Addr,
  379. pchString );
  380. }
  381. //
  382. // Address to string -- IP4
  383. //
  384. PWCHAR
  385. Dns_Ip4AddressToString_W(
  386. OUT PWCHAR pwString,
  387. IN PIP4_ADDRESS pIp4Addr
  388. )
  389. /*++
  390. Routine Description:
  391. Convert IP4 address to string format.
  392. Arguments:
  393. pwString -- buffer to hold string; MUST be at least
  394. IPV6_ADDRESS_STRING_LENGTH+1 in length
  395. pAddress -- IP4 address to convert to string
  396. Return Value:
  397. Ptr to next location in buffer (the terminating NULL).
  398. --*/
  399. {
  400. IP4_ADDRESS ip = *pIp4Addr;
  401. //
  402. // convert IP4 address to string
  403. // - address is in net order, lead byte in low memory
  404. //
  405. pwString += wsprintfW(
  406. pwString,
  407. L"%u.%u.%u.%u",
  408. (UCHAR) (ip & 0x000000ff),
  409. (UCHAR) ((ip & 0x0000ff00) >> 8),
  410. (UCHAR) ((ip & 0x00ff0000) >> 16),
  411. (UCHAR) ((ip & 0xff000000) >> 24)
  412. );
  413. return( pwString );
  414. }
  415. PCHAR
  416. Dns_Ip4AddressToString_A(
  417. OUT PCHAR pString,
  418. IN PIP4_ADDRESS pIp4Addr
  419. )
  420. /*++
  421. Routine Description:
  422. Convert IP4 address to string format.
  423. Arguments:
  424. pchString -- buffer to hold string; MUST be at least
  425. IPV6_ADDRESS_STRING_LENGTH+1 in length
  426. pAddress -- IP4 address to convert to string
  427. Return Value:
  428. Ptr to next location in buffer (the terminating NULL).
  429. --*/
  430. {
  431. IP4_ADDRESS ip = *pIp4Addr;
  432. //
  433. // convert IP4 address to string
  434. // - address is in net order, lead byte in low memory
  435. //
  436. pString += sprintf(
  437. pString,
  438. "%u.%u.%u.%u",
  439. (UCHAR) (ip & 0x000000ff),
  440. (UCHAR) ((ip & 0x0000ff00) >> 8),
  441. (UCHAR) ((ip & 0x00ff0000) >> 16),
  442. (UCHAR) ((ip & 0xff000000) >> 24)
  443. );
  444. return( pString );
  445. }
  446. //
  447. // Address-to-string -- combined IP4/6
  448. //
  449. PCHAR
  450. Dns_AddressToString_A(
  451. OUT PCHAR pchString,
  452. IN OUT PDWORD pStringLength,
  453. IN PBYTE pAddr,
  454. IN DWORD AddrLength,
  455. IN DWORD AddrFamily
  456. )
  457. /*++
  458. Routine Description:
  459. Convert address to string format.
  460. Arguments:
  461. pchString -- buffer to hold string; MUST be at least
  462. IPV6_ADDRESS_STRING_LENGTH+1 in length
  463. pStringLength -- string buffer length
  464. pAddr -- ptr to address
  465. AddrLength -- address length
  466. AddrFamily -- address family (AF_INET, AF_INET6)
  467. Return Value:
  468. Ptr to next location in buffer (the terminating NULL).
  469. NULL if no conversion.
  470. --*/
  471. {
  472. DWORD length = *pStringLength;
  473. // dispatch to conversion routine for this type
  474. if ( AddrFamily == AF_INET )
  475. {
  476. if ( length < IP4_ADDRESS_STRING_LENGTH+1 )
  477. {
  478. length = IP4_ADDRESS_STRING_LENGTH+1;
  479. goto Failed;
  480. }
  481. return Dns_Ip4AddressToString_A(
  482. pchString,
  483. (PIP4_ADDRESS) pAddr );
  484. }
  485. if ( AddrFamily == AF_INET6 )
  486. {
  487. if ( length < IP6_ADDRESS_STRING_LENGTH+1 )
  488. {
  489. length = IP6_ADDRESS_STRING_LENGTH+1;
  490. goto Failed;
  491. }
  492. return Dns_Ip6AddressToString_A(
  493. pchString,
  494. (PIP6_ADDRESS) pAddr );
  495. }
  496. Failed:
  497. *pStringLength = length;
  498. return NULL;
  499. }
  500. //
  501. // DNS_ADDR-to-string
  502. //
  503. PCHAR
  504. Dns_DnsAddrToString_A(
  505. OUT PCHAR pBuffer,
  506. IN OUT PDWORD pBufLength,
  507. IN PDNS_ADDR pAddr
  508. )
  509. /*++
  510. Routine Description:
  511. Convert address to string format.
  512. Arguments:
  513. pBuffer -- buffer to hold string;
  514. if pBufLength not given, then MUST be at least
  515. IPV6_ADDRESS_STRING_LENGTH+1 in length
  516. pBufLength -- ptr to string buffer length
  517. pAddr -- ptr to address
  518. Return Value:
  519. Ptr to next location in buffer (the terminating NULL).
  520. NULL if no conversion.
  521. --*/
  522. {
  523. DNS_STATUS status;
  524. //
  525. // DCR: handle no buffer length given -- handles IP6 default?
  526. //
  527. //
  528. // print support for IP4/IP6
  529. //
  530. if ( DnsAddr_IsIp4(pAddr) )
  531. {
  532. status = RtlIpv4AddressToStringExA(
  533. &pAddr->SockaddrIn.sin_addr,
  534. pAddr->SockaddrIn.sin_port,
  535. pBuffer,
  536. pBufLength );
  537. }
  538. else if ( DnsAddr_IsIp6(pAddr) )
  539. {
  540. status = RtlIpv6AddressToStringExA(
  541. &pAddr->SockaddrIn6.sin6_addr,
  542. pAddr->SockaddrIn6.sin6_scope_id,
  543. pAddr->SockaddrIn6.sin6_port,
  544. pBuffer,
  545. pBufLength );
  546. }
  547. else
  548. {
  549. status = ERROR_INVALID_PARAMETER;
  550. if ( !pBufLength || *pBufLength > 40 )
  551. {
  552. sprintf(
  553. pBuffer,
  554. "Invalid DNS_ADDR at %p",
  555. pAddr );
  556. }
  557. pBuffer = NULL;
  558. }
  559. //
  560. // return ptr to next char in buffer
  561. //
  562. if ( status == NO_ERROR )
  563. {
  564. pBuffer += *pBufLength;
  565. }
  566. else
  567. {
  568. pBuffer = NULL;
  569. }
  570. return pBuffer;
  571. }
  572. PWCHAR
  573. Dns_DnsAddrToString_W(
  574. OUT PWCHAR pBuffer,
  575. IN PDWORD pBufLength,
  576. IN PDNS_ADDR pAddr
  577. )
  578. {
  579. DNS_STATUS status;
  580. //
  581. // print support for IP4/IP6
  582. //
  583. if ( DnsAddr_IsIp4(pAddr) )
  584. {
  585. status = RtlIpv4AddressToStringExW(
  586. &pAddr->SockaddrIn.sin_addr,
  587. pAddr->SockaddrIn.sin_port,
  588. pBuffer,
  589. pBufLength );
  590. }
  591. else if ( DnsAddr_IsIp6(pAddr) )
  592. {
  593. status = RtlIpv6AddressToStringExW(
  594. &pAddr->SockaddrIn6.sin6_addr,
  595. pAddr->SockaddrIn6.sin6_scope_id,
  596. pAddr->SockaddrIn6.sin6_port,
  597. pBuffer,
  598. pBufLength );
  599. }
  600. else
  601. {
  602. status = ERROR_INVALID_PARAMETER;
  603. if ( !pBufLength || *pBufLength > 40 )
  604. {
  605. wsprintfW(
  606. pBuffer,
  607. L"Invalid DNS_ADDR at %p",
  608. pAddr );
  609. }
  610. pBuffer = NULL;
  611. }
  612. //
  613. // return ptr to next char in buffer
  614. //
  615. if ( status == NO_ERROR )
  616. {
  617. pBuffer += *pBufLength;
  618. }
  619. else
  620. {
  621. pBuffer = NULL;
  622. }
  623. return pBuffer;
  624. }
  625. //
  626. // Reverse lookup address-to-name IP4
  627. //
  628. PCHAR
  629. Dns_Ip4AddressToReverseName_A(
  630. OUT PCHAR pBuffer,
  631. IN IP4_ADDRESS IpAddress
  632. )
  633. /*++
  634. Routine Description:
  635. Write reverse lookup name, given corresponding IP
  636. Arguments:
  637. pBuffer -- ptr to buffer for reverse lookup name;
  638. MUST contain at least DNS_MAX_REVERSE_NAME_BUFFER_LENGTH bytes
  639. IpAddress -- IP address to create
  640. Return Value:
  641. Ptr to next location in buffer.
  642. --*/
  643. {
  644. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseName_A()\n" ));
  645. //
  646. // write digits for each octect in IP address
  647. // - note, it is in net order so lowest octect, is in highest memory
  648. //
  649. pBuffer += sprintf(
  650. pBuffer,
  651. "%u.%u.%u.%u.in-addr.arpa.",
  652. (UCHAR) ((IpAddress & 0xff000000) >> 24),
  653. (UCHAR) ((IpAddress & 0x00ff0000) >> 16),
  654. (UCHAR) ((IpAddress & 0x0000ff00) >> 8),
  655. (UCHAR) (IpAddress & 0x000000ff) );
  656. return( pBuffer );
  657. }
  658. PWCHAR
  659. Dns_Ip4AddressToReverseName_W(
  660. OUT PWCHAR pBuffer,
  661. IN IP4_ADDRESS IpAddress
  662. )
  663. /*++
  664. Routine Description:
  665. Write reverse lookup name, given corresponding IP
  666. Arguments:
  667. pBuffer -- ptr to buffer for reverse lookup name;
  668. MUST contain at least DNS_MAX_REVERSE_NAME_BUFFER_LENGTH wide chars
  669. IpAddress -- IP address to create
  670. Return Value:
  671. Ptr to next location in buffer.
  672. --*/
  673. {
  674. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseName_W()\n" ));
  675. //
  676. // write digits for each octect in IP address
  677. // - note, it is in net order so lowest octect, is in highest memory
  678. //
  679. pBuffer += wsprintfW(
  680. pBuffer,
  681. L"%u.%u.%u.%u.in-addr.arpa.",
  682. (UCHAR) ((IpAddress & 0xff000000) >> 24),
  683. (UCHAR) ((IpAddress & 0x00ff0000) >> 16),
  684. (UCHAR) ((IpAddress & 0x0000ff00) >> 8),
  685. (UCHAR) (IpAddress & 0x000000ff) );
  686. return( pBuffer );
  687. }
  688. PCHAR
  689. Dns_Ip4AddressToReverseNameAlloc_A(
  690. IN IP4_ADDRESS IpAddress
  691. )
  692. /*++
  693. Routine Description:
  694. Create reverse lookup name string, given corresponding IP.
  695. Caller must free the string.
  696. Arguments:
  697. IpAddress -- IP address to create
  698. Return Value:
  699. Ptr to new reverse lookup string.
  700. --*/
  701. {
  702. PCHAR pch;
  703. PCHAR pchend;
  704. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseNameAlloc_A()\n" ));
  705. //
  706. // allocate space for string
  707. //
  708. pch = ALLOCATE_HEAP( DNS_MAX_REVERSE_NAME_BUFFER_LENGTH );
  709. if ( !pch )
  710. {
  711. return( NULL );
  712. }
  713. //
  714. // write string for IP
  715. //
  716. pchend = Dns_Ip4AddressToReverseName_A( pch, IpAddress );
  717. if ( !pchend )
  718. {
  719. FREE_HEAP( pch );
  720. return( NULL );
  721. }
  722. return( pch );
  723. }
  724. PWCHAR
  725. Dns_Ip4AddressToReverseNameAlloc_W(
  726. IN IP4_ADDRESS IpAddress
  727. )
  728. /*++
  729. Routine Description:
  730. Create reverse lookup name string, given corresponding IP.
  731. Caller must free the string.
  732. Arguments:
  733. IpAddress -- IP address to create
  734. Return Value:
  735. Ptr to new reverse lookup string.
  736. --*/
  737. {
  738. PWCHAR pch;
  739. PWCHAR pchend;
  740. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseNameAlloc_W()\n" ));
  741. //
  742. // allocate space for string
  743. //
  744. pch = ALLOCATE_HEAP( DNS_MAX_REVERSE_NAME_BUFFER_LENGTH * sizeof(WCHAR) );
  745. if ( !pch )
  746. {
  747. return( NULL );
  748. }
  749. //
  750. // write string for IP
  751. //
  752. pchend = Dns_Ip4AddressToReverseName_W( pch, IpAddress );
  753. if ( !pchend )
  754. {
  755. FREE_HEAP( pch );
  756. return( NULL );
  757. }
  758. return( pch );
  759. }
  760. //
  761. // Reverse lookup address-to-name -- IP6
  762. //
  763. PCHAR
  764. Dns_Ip6AddressToReverseName_A(
  765. OUT PCHAR pBuffer,
  766. IN IP6_ADDRESS Ip6Addr
  767. )
  768. /*++
  769. Routine Description:
  770. Write reverse lookup name, given corresponding IP6 address
  771. Arguments:
  772. pBuffer -- ptr to buffer for reverse lookup name;
  773. MUST contain at least DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH bytes
  774. Ip6Addr -- IP6 address to create reverse string for
  775. Return Value:
  776. Ptr to next location in buffer.
  777. --*/
  778. {
  779. DWORD i;
  780. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseName_A()\n" ));
  781. //
  782. // write digit for each nibble in IP6 address
  783. //
  784. // note we are reversing net order here
  785. // since address is in net order and we are filling
  786. // in least to most significant order
  787. // - go DOWN through DWORDS
  788. // - go DOWN through the BYTES
  789. // - but we must put the lowest (least significant) nibble
  790. // first as our bits are not in "bit net order"
  791. // which is sending the highest bit in the byte first
  792. //
  793. #if 0
  794. i = 4;
  795. while ( i-- )
  796. {
  797. DWORD thisDword = Ip6Address.IP6Dword[i];
  798. pBuffer += sprintf(
  799. pBuffer,
  800. "%u.%u.%u.%u.%u.%u.%u.%u.",
  801. (thisDword & 0x0f000000) >> 24,
  802. (thisDword & 0xf0000000) >> 28,
  803. (thisDword & 0x000f0000) >> 16,
  804. (thisDword & 0x00f00000) >> 20,
  805. (thisDword & 0x00000f00) >> 8,
  806. (thisDword & 0x0000f000) >> 12,
  807. (thisDword & 0x0000000f) ,
  808. (thisDword & 0x000000f0) >> 4
  809. );
  810. }
  811. #endif
  812. i = 16;
  813. while ( i-- )
  814. {
  815. BYTE thisByte = Ip6Addr.IP6Byte[i];
  816. pBuffer += sprintf(
  817. pBuffer,
  818. "%x.%x.",
  819. (thisByte & 0x0f),
  820. (thisByte & 0xf0) >> 4
  821. );
  822. }
  823. pBuffer += sprintf(
  824. pBuffer,
  825. DNS_IP6_REVERSE_DOMAIN_STRING );
  826. return( pBuffer );
  827. }
  828. PWCHAR
  829. Dns_Ip6AddressToReverseName_W(
  830. OUT PWCHAR pBuffer,
  831. IN IP6_ADDRESS Ip6Addr
  832. )
  833. /*++
  834. Routine Description:
  835. Write reverse lookup name, given corresponding IP6 address
  836. Arguments:
  837. pBuffer -- ptr to buffer for reverse lookup name;
  838. MUST contain at least DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH wide chars
  839. Ip6Addr -- IP6 address to create reverse string for
  840. Return Value:
  841. Ptr to next location in buffer.
  842. --*/
  843. {
  844. DWORD i;
  845. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseName_W()\n" ));
  846. //
  847. // write digit for each nibble in IP6 address
  848. // - in net order so lowest nibble is in highest memory
  849. //
  850. i = 16;
  851. while ( i-- )
  852. {
  853. BYTE thisByte = Ip6Addr.IP6Byte[i];
  854. pBuffer += wsprintfW(
  855. pBuffer,
  856. L"%x.%x.",
  857. (thisByte & 0x0f),
  858. (thisByte & 0xf0) >> 4
  859. );
  860. }
  861. pBuffer += wsprintfW(
  862. pBuffer,
  863. DNS_IP6_REVERSE_DOMAIN_STRING_W );
  864. return( pBuffer );
  865. }
  866. PCHAR
  867. Dns_Ip6AddressToReverseNameAlloc_A(
  868. IN IP6_ADDRESS Ip6Addr
  869. )
  870. /*++
  871. Routine Description:
  872. Create reverse lookup name given corresponding IP.
  873. Caller must free the string.
  874. Arguments:
  875. Ip6Addr -- IP6 address to create reverse name for
  876. Return Value:
  877. Ptr to new reverse lookup name string.
  878. --*/
  879. {
  880. PCHAR pch;
  881. PCHAR pchend;
  882. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseNameAlloc_A()\n" ));
  883. //
  884. // allocate space for string
  885. //
  886. pch = ALLOCATE_HEAP( DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH );
  887. if ( !pch )
  888. {
  889. return( NULL );
  890. }
  891. //
  892. // write string for IP
  893. //
  894. pchend = Dns_Ip6AddressToReverseName_A( pch, Ip6Addr );
  895. if ( !pchend )
  896. {
  897. FREE_HEAP( pch );
  898. return( NULL );
  899. }
  900. return( pch );
  901. }
  902. PWCHAR
  903. Dns_Ip6AddressToReverseNameAlloc_W(
  904. IN IP6_ADDRESS Ip6Addr
  905. )
  906. /*++
  907. Routine Description:
  908. Create reverse lookup name given corresponding IP.
  909. Caller must free the string.
  910. Arguments:
  911. Ip6Addr -- IP6 address to create reverse name for
  912. Return Value:
  913. Ptr to new reverse lookup name string.
  914. --*/
  915. {
  916. PWCHAR pch;
  917. PWCHAR pchend;
  918. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseNameAlloc_W()\n" ));
  919. //
  920. // allocate space for string
  921. //
  922. pch = (PWCHAR) ALLOCATE_HEAP(
  923. DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH * sizeof(WCHAR) );
  924. if ( !pch )
  925. {
  926. return( NULL );
  927. }
  928. //
  929. // write string for IP
  930. //
  931. pchend = Dns_Ip6AddressToReverseName_W( pch, Ip6Addr );
  932. if ( !pchend )
  933. {
  934. FREE_HEAP( pch );
  935. return( NULL );
  936. }
  937. return( pch );
  938. }
  939. //
  940. // Reverse name-to-address -- IP4
  941. //
  942. BOOL
  943. Dns_Ip4ReverseNameToAddress_A(
  944. OUT PIP4_ADDRESS pIp4Addr,
  945. IN PCSTR pszName
  946. )
  947. /*++
  948. Routine Description:
  949. Get IP for reverse lookup name.
  950. Arguments:
  951. pIp4Addr -- addr to receive IP address if found
  952. pszName -- name to lookup
  953. Return Value:
  954. TRUE -- if reverse lookup name converted to IP
  955. FALSE -- if not IP4 reverse lookup name
  956. --*/
  957. {
  958. #define SIZE_IP4REV (sizeof(".in-addr.arpa")-1)
  959. CHAR nameBuffer[ DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH+1 ];
  960. DWORD nameLength;
  961. IP4_ADDRESS ip;
  962. PCHAR pch;
  963. DWORD i;
  964. DWORD byte;
  965. DNSDBG( TRACE, (
  966. "Dns_Ip4ReverseNameToAddress_A( %s )\n",
  967. pszName ));
  968. //
  969. // validate name
  970. // fail if
  971. // - too long
  972. // - too short
  973. // - not in in-addr.arpa domain
  974. //
  975. nameLength = strlen( pszName );
  976. if ( nameLength > DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH )
  977. {
  978. return( FALSE );
  979. }
  980. if ( pszName[nameLength-1] == '.' )
  981. {
  982. nameLength--;
  983. }
  984. if ( nameLength <= SIZE_IP4REV )
  985. {
  986. return( FALSE );
  987. }
  988. nameLength -= SIZE_IP4REV;
  989. if ( _strnicmp( ".in-addr.arpa", &pszName[nameLength], SIZE_IP4REV ) != 0 )
  990. {
  991. return( FALSE );
  992. }
  993. //
  994. // copy reverse dotted decimal piece of name
  995. //
  996. RtlCopyMemory(
  997. nameBuffer,
  998. pszName,
  999. nameLength );
  1000. nameBuffer[nameLength] = 0;
  1001. //
  1002. // read digits
  1003. //
  1004. ip = 0;
  1005. i = 0;
  1006. pch = nameBuffer + nameLength;
  1007. while ( 1 )
  1008. {
  1009. --pch;
  1010. if ( *pch == '.' )
  1011. {
  1012. *pch = 0;
  1013. pch++;
  1014. }
  1015. else if ( pch == nameBuffer )
  1016. {
  1017. }
  1018. else
  1019. {
  1020. continue;
  1021. }
  1022. // convert byte
  1023. byte = strtoul( pch, NULL, 10 );
  1024. if ( byte > 255 )
  1025. {
  1026. return( FALSE );
  1027. }
  1028. if ( i > 3 )
  1029. {
  1030. return( FALSE );
  1031. }
  1032. ip |= byte << (8*i);
  1033. // terminate at string beginning
  1034. // or continue back up string
  1035. if ( pch == nameBuffer )
  1036. {
  1037. break;
  1038. }
  1039. i++;
  1040. pch--;
  1041. }
  1042. *pIp4Addr = ip;
  1043. DNSDBG( TRACE, (
  1044. "Success on Dns_Ip4ReverseNameToAddress_A( %s ) => %s\n",
  1045. pszName,
  1046. IP4_STRING(ip) ));
  1047. return( TRUE );
  1048. }
  1049. BOOL
  1050. Dns_Ip4ReverseNameToAddress_W(
  1051. OUT PIP4_ADDRESS pIp4Addr,
  1052. IN PCWSTR pwsName
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. Get IP for reverse lookup name.
  1057. Arguments:
  1058. pIp4Addr -- addr to receive IP address if found
  1059. pszName -- name to lookup
  1060. Return Value:
  1061. TRUE -- if reverse lookup name converted to IP
  1062. FALSE -- if not IP4 reverse lookup name
  1063. --*/
  1064. {
  1065. CHAR nameBuffer[ DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH+1 ];
  1066. DWORD bufLength;
  1067. DWORD nameLengthUtf8;
  1068. DNSDBG( TRACE, (
  1069. "Dns_Ip4ReverseNameToAddress_W( %S )\n",
  1070. pwsName ));
  1071. //
  1072. // convert to UTF8
  1073. // - use UTF8 since conversion to it is trivial and it
  1074. // is identical to ANSI for all reverse lookup names
  1075. //
  1076. bufLength = DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH + 1;
  1077. nameLengthUtf8 = Dns_StringCopy(
  1078. nameBuffer,
  1079. & bufLength,
  1080. (PCHAR) pwsName,
  1081. 0, // NULL terminated
  1082. DnsCharSetUnicode,
  1083. DnsCharSetUtf8 );
  1084. if ( nameLengthUtf8 == 0 )
  1085. {
  1086. return FALSE;
  1087. }
  1088. //
  1089. // call ANSI routine to do conversion
  1090. //
  1091. return Dns_Ip4ReverseNameToAddress_A(
  1092. pIp4Addr,
  1093. (PCSTR) nameBuffer );
  1094. }
  1095. //
  1096. // Reverse name-to-address -- IP6
  1097. //
  1098. BOOL
  1099. Dns_Ip6ReverseNameToAddress_A(
  1100. OUT PIP6_ADDRESS pIp6Addr,
  1101. IN PCSTR pszName
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. Get IP6 address for reverse lookup name.
  1106. Arguments:
  1107. pIp6Addr -- addr to receive IP address if found
  1108. pszName -- name to lookup
  1109. Return Value:
  1110. TRUE -- if reverse lookup name converted to IP
  1111. FALSE -- if not IP4 reverse lookup name
  1112. --*/
  1113. {
  1114. #define SIZE_IP6REV (sizeof(".ip6.arpa")-1)
  1115. CHAR nameBuffer[ DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH+1 ];
  1116. DWORD nameLength;
  1117. PCHAR pch;
  1118. BYTE byteArray[16];
  1119. DWORD byteCount;
  1120. DWORD nibble;
  1121. DWORD highNibble;
  1122. BOOL fisLow;
  1123. DNSDBG( TRACE, ( "Dns_Ip6ReverseNameToAddress_A()\n" ));
  1124. //
  1125. // validate name
  1126. // fail if
  1127. // - too long
  1128. // - too short
  1129. // - not in in6.int domain
  1130. //
  1131. nameLength = strlen( pszName );
  1132. if ( nameLength > DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH )
  1133. {
  1134. return( FALSE );
  1135. }
  1136. if ( pszName[nameLength-1] == '.' )
  1137. {
  1138. nameLength--;
  1139. }
  1140. if ( nameLength <= SIZE_IP6REV )
  1141. {
  1142. return( FALSE );
  1143. }
  1144. nameLength -= SIZE_IP6REV;
  1145. if ( _strnicmp( ".ip6.arpa", &pszName[nameLength], SIZE_IP6REV ) != 0 )
  1146. {
  1147. return( FALSE );
  1148. }
  1149. //
  1150. // copy name
  1151. //
  1152. RtlCopyMemory(
  1153. nameBuffer,
  1154. pszName,
  1155. nameLength );
  1156. nameBuffer[nameLength] = 0;
  1157. //
  1158. // clear IP6 address
  1159. // - need for partial reverse lookup name
  1160. //
  1161. RtlZeroMemory(
  1162. byteArray,
  1163. sizeof(byteArray) );
  1164. //
  1165. // read digits
  1166. //
  1167. byteCount = 0;
  1168. fisLow = FALSE;
  1169. pch = nameBuffer + nameLength;
  1170. while ( 1 )
  1171. {
  1172. if ( byteCount > 15 )
  1173. {
  1174. return( FALSE );
  1175. }
  1176. --pch;
  1177. if ( *pch == '.' )
  1178. {
  1179. *pch = 0;
  1180. pch++;
  1181. }
  1182. else if ( pch == nameBuffer )
  1183. {
  1184. }
  1185. else
  1186. {
  1187. // DCR: multi-digit nibbles in reverse name -- error?
  1188. continue;
  1189. }
  1190. // convert nibble
  1191. // - zero test special as
  1192. // A) faster
  1193. // B) strtoul() uses for error case
  1194. if ( *pch == '0' )
  1195. {
  1196. nibble = 0;
  1197. }
  1198. else
  1199. {
  1200. nibble = strtoul( pch, NULL, 16 );
  1201. if ( nibble == 0 || nibble > 15 )
  1202. {
  1203. return( FALSE );
  1204. }
  1205. }
  1206. // save high nibble
  1207. // on low nibble, write byte to IP6 address
  1208. if ( !fisLow )
  1209. {
  1210. highNibble = nibble;
  1211. fisLow = TRUE;
  1212. }
  1213. else
  1214. {
  1215. //byteArray[byteCount++] = (BYTE) (lowNibble | (nibble << 4));
  1216. pIp6Addr->IP6Byte[byteCount++] = (BYTE) ( (highNibble<<4) | nibble );
  1217. fisLow = FALSE;
  1218. }
  1219. // terminate at string beginning
  1220. // or continue back up string
  1221. if ( pch == nameBuffer )
  1222. {
  1223. break;
  1224. }
  1225. pch--;
  1226. }
  1227. //*pIp6Addr = *(PIP6_ADDRESS) byteArray;
  1228. DNSDBG( TRACE, (
  1229. "Success on Dns_Ip6ReverseNameToAddress_A( %s )\n",
  1230. pszName ));
  1231. return( TRUE );
  1232. }
  1233. BOOL
  1234. Dns_Ip6ReverseNameToAddress_W(
  1235. OUT PIP6_ADDRESS pIp6Addr,
  1236. IN PCWSTR pwsName
  1237. )
  1238. /*++
  1239. Routine Description:
  1240. Get IP for reverse lookup name.
  1241. Arguments:
  1242. pIp6Addr -- addr to receive IP address if found
  1243. pszName -- name to lookup
  1244. Return Value:
  1245. TRUE -- if reverse lookup name converted to IP
  1246. FALSE -- if not IP6 reverse lookup name
  1247. --*/
  1248. {
  1249. CHAR nameBuffer[ DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH+1 ];
  1250. DWORD bufLength;
  1251. DWORD nameLengthUtf8;
  1252. DNSDBG( TRACE, (
  1253. "Dns_Ip6ReverseNameToAddress_W( %S )\n",
  1254. pwsName ));
  1255. //
  1256. // convert to UTF8
  1257. // - use UTF8 since conversion to it is trivial and it
  1258. // is identical to ANSI for all reverse lookup names
  1259. //
  1260. bufLength = DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH + 1;
  1261. nameLengthUtf8 = Dns_StringCopy(
  1262. nameBuffer,
  1263. & bufLength,
  1264. (PCHAR) pwsName,
  1265. 0, // NULL terminated
  1266. DnsCharSetUnicode,
  1267. DnsCharSetUtf8 );
  1268. if ( nameLengthUtf8 == 0 )
  1269. {
  1270. return FALSE;
  1271. }
  1272. //
  1273. // call ANSI routine to do conversion
  1274. //
  1275. return Dns_Ip6ReverseNameToAddress_A(
  1276. pIp6Addr,
  1277. (PCSTR) nameBuffer );
  1278. }
  1279. //
  1280. // Combined IP4/IP6 reverse-name-to-address
  1281. //
  1282. BOOL
  1283. Dns_ReverseNameToDnsAddr_W(
  1284. OUT PDNS_ADDR pAddr,
  1285. IN PCWSTR pString
  1286. )
  1287. /*++
  1288. Routine Description:
  1289. Build address (IP4 or IP6) from reverse lookup name.
  1290. Arguments:
  1291. pAddr -- DNS_ADDR to receive address
  1292. pString -- address string
  1293. Return Value:
  1294. TRUE if successful.
  1295. FALSE on error. GetLastError() for status.
  1296. --*/
  1297. {
  1298. return Dns_StringToDnsAddrEx(
  1299. pAddr,
  1300. (PCSTR) pString,
  1301. 0, // any family
  1302. TRUE, // unicode
  1303. TRUE // reverse
  1304. );
  1305. }
  1306. BOOL
  1307. Dns_ReverseNameToDnsAddr_A(
  1308. OUT PDNS_ADDR pAddr,
  1309. IN PCSTR pString
  1310. )
  1311. {
  1312. return Dns_StringToDnsAddrEx(
  1313. pAddr,
  1314. pString,
  1315. 0, // any family
  1316. FALSE, // not unicode
  1317. TRUE // reverse
  1318. );
  1319. }
  1320. //
  1321. // Could discontinue these and use DnsAddr
  1322. // version as NameToAddress_X version
  1323. //
  1324. BOOL
  1325. Dns_ReverseNameToAddress_W(
  1326. OUT PCHAR pAddrBuf,
  1327. IN OUT PDWORD pBufLength,
  1328. IN PCWSTR pString,
  1329. IN OUT PDWORD pAddrFamily
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. Build address (IP4 or IP6) from reverse lookup name.
  1334. Arguments:
  1335. pAddrBuf -- buffer to receive address
  1336. pBufLength -- ptr to address length
  1337. input - length of buffer
  1338. output - length of address found
  1339. pString -- address string
  1340. pAddrFamily -- ptr to address family
  1341. input - zero for any family or particular family to check
  1342. output - family found; zero if no conversion
  1343. Return Value:
  1344. TRUE if successful.
  1345. FALSE on error. GetLastError() for status.
  1346. --*/
  1347. {
  1348. return Dns_StringToAddressEx(
  1349. pAddrBuf,
  1350. pBufLength,
  1351. (PCSTR) pString,
  1352. pAddrFamily,
  1353. TRUE, // unicode
  1354. TRUE // reverse
  1355. );
  1356. }
  1357. BOOL
  1358. Dns_ReverseNameToAddress_A(
  1359. OUT PCHAR pAddrBuf,
  1360. IN OUT PDWORD pBufLength,
  1361. IN PCSTR pString,
  1362. IN OUT PDWORD pAddrFamily
  1363. )
  1364. {
  1365. return Dns_StringToAddressEx(
  1366. pAddrBuf,
  1367. pBufLength,
  1368. pString,
  1369. pAddrFamily,
  1370. FALSE, // ANSI
  1371. TRUE // reverse
  1372. );
  1373. }
  1374. //
  1375. // Combined string-to-address private workhorse
  1376. //
  1377. BOOL
  1378. Dns_StringToAddressEx(
  1379. OUT PCHAR pAddrBuf,
  1380. IN OUT PDWORD pBufLength,
  1381. IN PCSTR pString,
  1382. IN OUT PDWORD pAddrFamily,
  1383. IN BOOL fUnicode,
  1384. IN BOOL fReverse
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. Build address (IP4 or IP6 from string)
  1389. This routine is capable of all string-to-address
  1390. conversions and is the backbone of all the
  1391. combined string-to-address conversion routines.
  1392. Arguments:
  1393. pAddrBuf -- buffer to receive address
  1394. pBufLength -- ptr to address length
  1395. input - length of buffer
  1396. output - length of address found
  1397. pString -- address string
  1398. pAddrFamily -- ptr to address family
  1399. input - zero for any family or particular family to check
  1400. output - family found; zero if no conversion
  1401. fUnicode -- unicode string
  1402. fReverse -- reverse lookup string
  1403. Return Value:
  1404. TRUE if successful.
  1405. FALSE on error.
  1406. --*/
  1407. {
  1408. DNS_STATUS status = NO_ERROR;
  1409. DWORD length = 0;
  1410. INT family = *pAddrFamily;
  1411. DWORD bufLength = *pBufLength;
  1412. BOOL fconvert;
  1413. PCSTR preverseString;
  1414. CHAR nameBuffer[ DNS_MAX_REVERSE_NAME_BUFFER_LENGTH+1 ];
  1415. DNSDBG( TRACE, (
  1416. "Dns_StringToAddressEx( %S%s )\n",
  1417. fUnicode ? pString : "",
  1418. fUnicode ? "" : pString ));
  1419. //
  1420. // convert reverse to ANSI
  1421. //
  1422. // reverse lookups are done in ANSI; convert here to avoid
  1423. // double string conversion to check both IP4 and IP6
  1424. //
  1425. if ( fReverse )
  1426. {
  1427. preverseString = pString;
  1428. if ( fUnicode )
  1429. {
  1430. DWORD reverseLength = DNS_MAX_REVERSE_NAME_BUFFER_LENGTH;
  1431. if ( ! Dns_StringCopy(
  1432. nameBuffer,
  1433. & reverseLength,
  1434. (PCHAR) pString,
  1435. 0, // NULL terminated
  1436. DnsCharSetUnicode,
  1437. DnsCharSetUtf8 ) )
  1438. {
  1439. return FALSE;
  1440. }
  1441. preverseString = nameBuffer;
  1442. }
  1443. }
  1444. //
  1445. // check IP4
  1446. //
  1447. if ( family == 0 ||
  1448. family == AF_INET )
  1449. {
  1450. IP4_ADDRESS ip;
  1451. if ( fReverse )
  1452. {
  1453. fconvert = Dns_Ip4ReverseNameToAddress_A(
  1454. & ip,
  1455. preverseString );
  1456. }
  1457. else
  1458. {
  1459. if ( fUnicode )
  1460. {
  1461. fconvert = Dns_Ip4StringToAddress_W(
  1462. & ip,
  1463. (PCWSTR)pString );
  1464. }
  1465. else
  1466. {
  1467. fconvert = Dns_Ip4StringToAddress_A(
  1468. & ip,
  1469. pString );
  1470. }
  1471. }
  1472. if ( fconvert )
  1473. {
  1474. length = sizeof(IP4_ADDRESS);
  1475. family = AF_INET;
  1476. if ( bufLength < length )
  1477. {
  1478. status = ERROR_MORE_DATA;
  1479. }
  1480. else
  1481. {
  1482. * (PIP4_ADDRESS) pAddrBuf = ip;
  1483. }
  1484. DNSDBG( INIT2, (
  1485. "Converted string to IP4 address %s\n",
  1486. IP4_STRING(ip) ));
  1487. goto Done;
  1488. }
  1489. }
  1490. //
  1491. // check IP6
  1492. //
  1493. if ( family == 0 ||
  1494. family == AF_INET6 )
  1495. {
  1496. IP6_ADDRESS ip;
  1497. if ( fReverse )
  1498. {
  1499. fconvert = Dns_Ip6ReverseNameToAddress_A(
  1500. & ip,
  1501. preverseString );
  1502. }
  1503. else
  1504. {
  1505. if ( fUnicode )
  1506. {
  1507. fconvert = Dns_Ip6StringToAddress_W(
  1508. & ip,
  1509. (PCWSTR)pString );
  1510. }
  1511. else
  1512. {
  1513. fconvert = Dns_Ip6StringToAddress_A(
  1514. & ip,
  1515. pString );
  1516. }
  1517. }
  1518. if ( fconvert )
  1519. {
  1520. length = sizeof(IP6_ADDRESS);
  1521. if ( bufLength < length )
  1522. {
  1523. status = ERROR_MORE_DATA;
  1524. }
  1525. else
  1526. {
  1527. family = AF_INET6;
  1528. * (PIP6_ADDRESS) pAddrBuf = ip;
  1529. }
  1530. IF_DNSDBG( INIT2 )
  1531. {
  1532. DnsDbg_Ip6Address(
  1533. "Converted string to IP6 address: ",
  1534. (PIP6_ADDRESS) pAddrBuf,
  1535. "\n" );
  1536. }
  1537. goto Done;
  1538. }
  1539. }
  1540. length = 0;
  1541. family = 0;
  1542. status = DNS_ERROR_INVALID_IP_ADDRESS;
  1543. Done:
  1544. if ( status )
  1545. {
  1546. SetLastError( status );
  1547. }
  1548. *pAddrFamily = family;
  1549. *pBufLength = length;
  1550. DNSDBG( TRACE, (
  1551. "Leave Dns_StringToAddressEx()\n"
  1552. "\tstatus = %d\n"
  1553. "\tptr = %p\n"
  1554. "\tlength = %d\n"
  1555. "\tfamily = %d\n",
  1556. status,
  1557. pAddrBuf,
  1558. length,
  1559. family ));
  1560. return( status==ERROR_SUCCESS );
  1561. }
  1562. BOOL
  1563. Dns_StringToDnsAddrEx(
  1564. OUT PDNS_ADDR pAddr,
  1565. IN PCSTR pString,
  1566. IN DWORD Family, OPTIONAL
  1567. IN BOOL fUnicode,
  1568. IN BOOL fReverse
  1569. )
  1570. /*++
  1571. Routine Description:
  1572. Build address (IP4 or IP6 from string)
  1573. This routine is capable of all string-to-address
  1574. conversions and is the backbone of all the
  1575. combined string-to-address conversion routines.
  1576. Arguments:
  1577. pAddr -- ptr to DNS_ADDR to receive address
  1578. pString -- address string
  1579. Family -- if only accepting specific family; zero for any
  1580. fUnicode -- unicode string
  1581. fReverse -- reverse lookup string
  1582. Return Value:
  1583. TRUE if successful.
  1584. FALSE on error.
  1585. --*/
  1586. {
  1587. DNS_STATUS status = NO_ERROR;
  1588. DWORD length = 0;
  1589. BOOL fconvert;
  1590. PCSTR preverseString;
  1591. CHAR nameBuffer[ DNS_MAX_REVERSE_NAME_BUFFER_LENGTH+1 ];
  1592. DNSDBG( TRACE, (
  1593. "Dns_StringToDnsAddrEx( %S%s, rev=%d, unicode=%d )\n",
  1594. fUnicode ? pString : "",
  1595. fUnicode ? "" : pString,
  1596. fReverse,
  1597. fUnicode ));
  1598. //
  1599. // convert reverse to ANSI
  1600. //
  1601. // reverse lookups are done in ANSI; convert here to avoid
  1602. // double string conversion to check both IP4 and IP6
  1603. //
  1604. if ( fReverse )
  1605. {
  1606. preverseString = pString;
  1607. if ( fUnicode )
  1608. {
  1609. DWORD bufLength = DNS_MAX_REVERSE_NAME_BUFFER_LENGTH;
  1610. if ( ! Dns_StringCopy(
  1611. nameBuffer,
  1612. & bufLength,
  1613. (PCHAR) pString,
  1614. 0, // NULL terminated
  1615. DnsCharSetUnicode,
  1616. DnsCharSetUtf8 ) )
  1617. {
  1618. return FALSE;
  1619. }
  1620. preverseString = nameBuffer;
  1621. }
  1622. }
  1623. //
  1624. // check IP4
  1625. //
  1626. if ( Family == 0 || Family == AF_INET )
  1627. {
  1628. IP4_ADDRESS ip;
  1629. if ( fReverse )
  1630. {
  1631. fconvert = Dns_Ip4ReverseNameToAddress_A(
  1632. & ip,
  1633. preverseString );
  1634. }
  1635. else
  1636. {
  1637. if ( fUnicode )
  1638. {
  1639. fconvert = Dns_Ip4StringToAddress_W(
  1640. & ip,
  1641. (PCWSTR)pString );
  1642. }
  1643. else
  1644. {
  1645. fconvert = Dns_Ip4StringToAddress_A(
  1646. & ip,
  1647. pString );
  1648. }
  1649. }
  1650. if ( fconvert )
  1651. {
  1652. DnsAddr_BuildFromIp4(
  1653. pAddr,
  1654. ip,
  1655. 0 // no port
  1656. );
  1657. DNSDBG( INIT2, (
  1658. "Converted string to IP4 address %s\n",
  1659. IP4_STRING(ip) ));
  1660. goto Done;
  1661. }
  1662. }
  1663. //
  1664. // check IP6
  1665. //
  1666. if ( Family == 0 || Family == AF_INET6 )
  1667. {
  1668. if ( fReverse )
  1669. {
  1670. IP6_ADDRESS ip;
  1671. fconvert = Dns_Ip6ReverseNameToAddress_A(
  1672. & ip,
  1673. preverseString );
  1674. if ( fconvert )
  1675. {
  1676. DnsAddr_BuildFromIp6(
  1677. pAddr,
  1678. &ip,
  1679. 0, // no scope
  1680. 0 // no port
  1681. );
  1682. IF_DNSDBG( INIT2 )
  1683. {
  1684. DnsDbg_Ip6Address(
  1685. "Converted string to IP6 address: ",
  1686. (PIP6_ADDRESS) &ip,
  1687. "\n" );
  1688. }
  1689. goto Done;
  1690. }
  1691. }
  1692. else
  1693. {
  1694. DnsAddr_Clear( pAddr );
  1695. if ( fUnicode )
  1696. {
  1697. status = RtlIpv6StringToAddressExW(
  1698. (PCWSTR) pString,
  1699. & pAddr->SockaddrIn6.sin6_addr,
  1700. & pAddr->SockaddrIn6.sin6_scope_id,
  1701. & pAddr->SockaddrIn6.sin6_port
  1702. );
  1703. }
  1704. else
  1705. {
  1706. status = RtlIpv6StringToAddressExA(
  1707. (PCSTR) pString,
  1708. & pAddr->SockaddrIn6.sin6_addr,
  1709. & pAddr->SockaddrIn6.sin6_scope_id,
  1710. & pAddr->SockaddrIn6.sin6_port
  1711. );
  1712. }
  1713. if ( status == NO_ERROR )
  1714. {
  1715. pAddr->SockaddrIn6.sin6_family = AF_INET6;
  1716. pAddr->SockaddrLength = sizeof(SOCKADDR_IN6);
  1717. goto Done;
  1718. }
  1719. }
  1720. }
  1721. DnsAddr_Clear( pAddr );
  1722. status = DNS_ERROR_INVALID_IP_ADDRESS;
  1723. Done:
  1724. if ( status )
  1725. {
  1726. SetLastError( status );
  1727. }
  1728. DNSDBG( TRACE, (
  1729. "Leave Dns_StringToDnsAddrEx()\n"
  1730. "\tstatus = %d\n",
  1731. status ));
  1732. return( status==ERROR_SUCCESS );
  1733. }
  1734. //
  1735. // UPNP IP6 literal hack
  1736. //
  1737. WCHAR g_Ip6LiteralDomain[] = L".ipv6-literal.net";
  1738. DWORD g_Ip6LiteralDomainSize = sizeof(g_Ip6LiteralDomain);
  1739. VOID
  1740. Dns_Ip6AddressToLiteralName(
  1741. OUT PWCHAR pBuffer,
  1742. IN PIP6_ADDRESS pIp6
  1743. )
  1744. /*++
  1745. Routine Description:
  1746. Write UPNP-hack-literal.
  1747. Arguments:
  1748. pBuffer -- ptr to buffer for reverse lookup name;
  1749. MUST contain DNS_MAX_NAME_LENGTH characters.
  1750. pIp6 -- IP6 address to create reverse string for
  1751. Return Value:
  1752. None
  1753. --*/
  1754. {
  1755. DWORD length;
  1756. DNSDBG( TRACE, ( "Dns_Ip6AddressToLiteralName()\n" ));
  1757. //
  1758. // convert IP6 to address
  1759. //
  1760. Dns_Ip6AddressToString_W(
  1761. pBuffer,
  1762. pIp6 );
  1763. length = wcslen( pBuffer );
  1764. //
  1765. // replace all colons with dashes
  1766. //
  1767. String_ReplaceCharW(
  1768. pBuffer,
  1769. L':',
  1770. L'-' );
  1771. //
  1772. // write ip6 literal domain immediately after
  1773. //
  1774. wcscpy(
  1775. pBuffer + length,
  1776. g_Ip6LiteralDomain );
  1777. DNSDBG( TRACE, (
  1778. "Leave Dns_Ip6AddressToLiteralName() => %S\n",
  1779. pBuffer ));
  1780. }
  1781. BOOL
  1782. Dns_Ip6LiteralNameToAddress(
  1783. OUT PSOCKADDR_IN6 pSockAddr,
  1784. IN PCWSTR pwsString
  1785. )
  1786. /*++
  1787. Routine Description:
  1788. IP6 literal to IP6 sockaddr.
  1789. Arguments:
  1790. pSock6Addr -- address to fill with IP6 corresponding to literal
  1791. pwsString -- literal string
  1792. Return Value:
  1793. TRUE if IP6 literal found and convert.
  1794. FALSE if not IP6 literal.
  1795. --*/
  1796. {
  1797. WCHAR nameBuf[ DNS_MAX_NAME_LENGTH ];
  1798. DWORD iter;
  1799. DWORD length;
  1800. DWORD size;
  1801. PWCHAR pch;
  1802. PWCHAR pdomain;
  1803. DNS_STATUS status;
  1804. DNSDBG( TRACE, (
  1805. "Dns_Ip6LiteralNameToAddress( %S )\n",
  1806. pwsString ));
  1807. //
  1808. // test for literal
  1809. // - test undotted
  1810. // - test as FQDN
  1811. // note that even FQDN test is safe, as we insist
  1812. // that string size is GREATER than literal size
  1813. //
  1814. length = wcslen( pwsString );
  1815. size = (length+1) * sizeof(WCHAR);
  1816. if ( size <= g_Ip6LiteralDomainSize )
  1817. {
  1818. DNSDBG( INIT2, (
  1819. "Stopped UPNP parse -- short string.\n" ));
  1820. return FALSE;
  1821. }
  1822. pdomain = (PWSTR) ((PBYTE)pwsString + size - g_Ip6LiteralDomainSize);
  1823. if ( ! RtlEqualMemory(
  1824. pdomain,
  1825. g_Ip6LiteralDomain,
  1826. g_Ip6LiteralDomainSize-sizeof(WCHAR) ) )
  1827. {
  1828. pdomain--;
  1829. if ( pwsString[length-1] != L'.'
  1830. ||
  1831. ! RtlEqualMemory(
  1832. pdomain,
  1833. g_Ip6LiteralDomain,
  1834. g_Ip6LiteralDomainSize-sizeof(WCHAR) ) )
  1835. {
  1836. DNSDBG( INIT2, (
  1837. "Stopped UPNP parse -- no tag match.\n" ));
  1838. return FALSE;
  1839. }
  1840. }
  1841. //
  1842. // copy literal to buffer
  1843. //
  1844. if ( length >= DNS_MAX_NAME_LENGTH )
  1845. {
  1846. DNSDBG( INIT2, (
  1847. "Stopped UPNP parse -- big string.\n" ));
  1848. return FALSE;
  1849. }
  1850. length = (DWORD) ((PWSTR)pdomain - pwsString);
  1851. RtlCopyMemory(
  1852. nameBuf,
  1853. pwsString,
  1854. length*sizeof(WCHAR) );
  1855. nameBuf[ length ] = 0;
  1856. //
  1857. // replace dashes with colons
  1858. // replace 's' with % for scope
  1859. //
  1860. String_ReplaceCharW(
  1861. nameBuf,
  1862. L'-',
  1863. L':' );
  1864. String_ReplaceCharW(
  1865. nameBuf,
  1866. L's',
  1867. L'%' );
  1868. DNSDBG( INIT2, (
  1869. "Reconverted IP6 literal %S\n",
  1870. nameBuf ));
  1871. //
  1872. // convert to IP6 address
  1873. //
  1874. status = RtlIpv6StringToAddressExW(
  1875. (PCWSTR) nameBuf,
  1876. & pSockAddr->sin6_addr,
  1877. & pSockAddr->sin6_scope_id,
  1878. & pSockAddr->sin6_port
  1879. );
  1880. if ( status == NO_ERROR )
  1881. {
  1882. if ( IN6_IS_ADDR_LINKLOCAL( &pSockAddr->sin6_addr )
  1883. ||
  1884. IN6_IS_ADDR_SITELOCAL( &pSockAddr->sin6_addr ) )
  1885. {
  1886. pSockAddr->sin6_flowinfo = 0;
  1887. pSockAddr->sin6_family = AF_INET6;
  1888. }
  1889. else
  1890. {
  1891. status = ERROR_INVALID_PARAMETER;
  1892. }
  1893. }
  1894. return( status == NO_ERROR );
  1895. }
  1896. //
  1897. // End straddr.c
  1898. //