Source code of Windows XP (NT5)
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.

1863 lines
36 KiB

  1. /*++
  2. Copyright (c) 1996-2001 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_StringToAddress_W(
  250. OUT PCHAR pAddrBuf,
  251. IN OUT PDWORD pBufLength,
  252. IN PCWSTR pString,
  253. IN OUT PDWORD pAddrFamily
  254. )
  255. /*++
  256. Routine Description:
  257. Build address (IP4 or IP6) from address string.
  258. Arguments:
  259. pAddrBuf -- buffer to receive address
  260. pBufLength -- ptr to address length
  261. input - length of buffer
  262. output - length of address found
  263. pString -- address string
  264. pAddrFamily -- ptr to address family
  265. input - zero for any family or particular family to check
  266. output - family found; zero if no conversion
  267. Return Value:
  268. TRUE if successful.
  269. FALSE on error. GetLastError() for status.
  270. --*/
  271. {
  272. return Dns_StringToAddressEx(
  273. pAddrBuf,
  274. pBufLength,
  275. (PCSTR) pString,
  276. pAddrFamily,
  277. TRUE, // unicode
  278. FALSE // forward
  279. );
  280. }
  281. BOOL
  282. Dns_StringToAddress_A(
  283. OUT PCHAR pAddrBuf,
  284. IN OUT PDWORD pBufLength,
  285. IN PCSTR pString,
  286. IN OUT PDWORD pAddrFamily
  287. )
  288. {
  289. return Dns_StringToAddressEx(
  290. pAddrBuf,
  291. pBufLength,
  292. pString,
  293. pAddrFamily,
  294. FALSE, // ANSI
  295. FALSE // forward
  296. );
  297. }
  298. //
  299. // Address to string
  300. //
  301. PWCHAR
  302. Dns_Ip6AddressToString_W(
  303. OUT PWCHAR pwString,
  304. IN PIP6_ADDRESS pIp6Addr
  305. )
  306. /*++
  307. Routine Description:
  308. Convert IP6 address to string format.
  309. Arguments:
  310. pwString -- buffer to hold string; MUST be at least
  311. IPV6_ADDRESS_STRING_LENGTH+1 in length
  312. pAddress -- IP6 address to convert to string
  313. Return Value:
  314. Ptr to next location in buffer (the terminating NULL).
  315. --*/
  316. {
  317. // DCR: could be macro
  318. return RtlIpv6AddressToStringW(
  319. (PIN6_ADDR) pIp6Addr,
  320. pwString );
  321. }
  322. PCHAR
  323. Dns_Ip6AddressToString_A(
  324. OUT PCHAR pchString,
  325. IN PIP6_ADDRESS pIp6Addr
  326. )
  327. /*++
  328. Routine Description:
  329. Convert IP6 address to string format.
  330. Arguments:
  331. pchString -- buffer to hold string; MUST be at least
  332. IPV6_ADDRESS_STRING_LENGTH+1 in length
  333. pAddress -- IP6 address to convert to string
  334. Return Value:
  335. Ptr to next location in buffer (the terminating NULL).
  336. --*/
  337. {
  338. // DCR: could be macro
  339. return RtlIpv6AddressToStringA(
  340. (PIN6_ADDR) pIp6Addr,
  341. pchString );
  342. }
  343. //
  344. // Address to string -- IP4
  345. //
  346. PWCHAR
  347. Dns_Ip4AddressToString_W(
  348. OUT PWCHAR pwString,
  349. IN PIP4_ADDRESS pIp4Addr
  350. )
  351. /*++
  352. Routine Description:
  353. Convert IP4 address to string format.
  354. Arguments:
  355. pwString -- buffer to hold string; MUST be at least
  356. IPV6_ADDRESS_STRING_LENGTH+1 in length
  357. pAddress -- IP4 address to convert to string
  358. Return Value:
  359. Ptr to next location in buffer (the terminating NULL).
  360. --*/
  361. {
  362. IP4_ADDRESS ip = *pIp4Addr;
  363. //
  364. // convert IP4 address to string
  365. // - address is in net order, lead byte in low memory
  366. //
  367. pwString += wsprintfW(
  368. pwString,
  369. L"%u.%u.%u.%u",
  370. (UCHAR) (ip & 0x000000ff),
  371. (UCHAR) ((ip & 0x0000ff00) >> 8),
  372. (UCHAR) ((ip & 0x00ff0000) >> 16),
  373. (UCHAR) ((ip & 0xff000000) >> 24)
  374. );
  375. return( pwString );
  376. }
  377. PCHAR
  378. Dns_Ip4AddressToString_A(
  379. OUT PCHAR pString,
  380. IN PIP4_ADDRESS pIp4Addr
  381. )
  382. /*++
  383. Routine Description:
  384. Convert IP4 address to string format.
  385. Arguments:
  386. pchString -- buffer to hold string; MUST be at least
  387. IPV6_ADDRESS_STRING_LENGTH+1 in length
  388. pAddress -- IP4 address to convert to string
  389. Return Value:
  390. Ptr to next location in buffer (the terminating NULL).
  391. --*/
  392. {
  393. IP4_ADDRESS ip = *pIp4Addr;
  394. //
  395. // convert IP4 address to string
  396. // - address is in net order, lead byte in low memory
  397. //
  398. pString += sprintf(
  399. pString,
  400. "%u.%u.%u.%u",
  401. (UCHAR) (ip & 0x000000ff),
  402. (UCHAR) ((ip & 0x0000ff00) >> 8),
  403. (UCHAR) ((ip & 0x00ff0000) >> 16),
  404. (UCHAR) ((ip & 0xff000000) >> 24)
  405. );
  406. return( pString );
  407. }
  408. //
  409. // Address-to-string -- combined IP4/6
  410. //
  411. PCHAR
  412. Dns_AddressToString_A(
  413. OUT PCHAR pchString,
  414. IN OUT PDWORD pStringLength,
  415. IN PBYTE pAddr,
  416. IN DWORD AddrLength,
  417. IN DWORD AddrFamily
  418. )
  419. /*++
  420. Routine Description:
  421. Convert address to string format.
  422. Arguments:
  423. pchString -- buffer to hold string; MUST be at least
  424. IPV6_ADDRESS_STRING_LENGTH+1 in length
  425. pStringLength -- string buffer length
  426. pAddr -- ptr to address
  427. AddrLength -- address length
  428. AddrFamily -- address family (AF_INET, AF_INET6)
  429. Return Value:
  430. Ptr to next location in buffer (the terminating NULL).
  431. NULL if no conversion.
  432. --*/
  433. {
  434. DWORD length = *pStringLength;
  435. // dispatch to conversion routine for this type
  436. if ( AddrFamily == AF_INET )
  437. {
  438. if ( length < IP_ADDRESS_STRING_LENGTH+1 )
  439. {
  440. length = IP_ADDRESS_STRING_LENGTH+1;
  441. goto Failed;
  442. }
  443. return Dns_Ip4AddressToString_A(
  444. pchString,
  445. (PIP4_ADDRESS) pAddr );
  446. }
  447. if ( AddrFamily == AF_INET6 )
  448. {
  449. if ( length < IP6_ADDRESS_STRING_LENGTH+1 )
  450. {
  451. length = IP6_ADDRESS_STRING_LENGTH+1;
  452. goto Failed;
  453. }
  454. return Dns_Ip6AddressToString_A(
  455. pchString,
  456. (PIP6_ADDRESS) pAddr );
  457. }
  458. Failed:
  459. *pStringLength = length;
  460. return NULL;
  461. }
  462. //
  463. // Reverse lookup address-to-name IP4
  464. //
  465. PCHAR
  466. Dns_Ip4AddressToReverseName_A(
  467. OUT PCHAR pBuffer,
  468. IN IP_ADDRESS IpAddress
  469. )
  470. /*++
  471. Routine Description:
  472. Write reverse lookup name, given corresponding IP
  473. Arguments:
  474. pBuffer -- ptr to buffer for reverse lookup name;
  475. MUST contain at least DNS_MAX_REVERSE_NAME_BUFFER_LENGTH bytes
  476. IpAddress -- IP address to create
  477. Return Value:
  478. Ptr to next location in buffer.
  479. --*/
  480. {
  481. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseName_A()\n" ));
  482. //
  483. // write digits for each octect in IP address
  484. // - note, it is in net order so lowest octect, is in highest memory
  485. //
  486. pBuffer += sprintf(
  487. pBuffer,
  488. "%u.%u.%u.%u.in-addr.arpa.",
  489. (UCHAR) ((IpAddress & 0xff000000) >> 24),
  490. (UCHAR) ((IpAddress & 0x00ff0000) >> 16),
  491. (UCHAR) ((IpAddress & 0x0000ff00) >> 8),
  492. (UCHAR) (IpAddress & 0x000000ff) );
  493. return( pBuffer );
  494. }
  495. PWCHAR
  496. Dns_Ip4AddressToReverseName_W(
  497. OUT PWCHAR pBuffer,
  498. IN IP_ADDRESS IpAddress
  499. )
  500. /*++
  501. Routine Description:
  502. Write reverse lookup name, given corresponding IP
  503. Arguments:
  504. pBuffer -- ptr to buffer for reverse lookup name;
  505. MUST contain at least DNS_MAX_REVERSE_NAME_BUFFER_LENGTH wide chars
  506. IpAddress -- IP address to create
  507. Return Value:
  508. Ptr to next location in buffer.
  509. --*/
  510. {
  511. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseName_W()\n" ));
  512. //
  513. // write digits for each octect in IP address
  514. // - note, it is in net order so lowest octect, is in highest memory
  515. //
  516. pBuffer += wsprintfW(
  517. pBuffer,
  518. L"%u.%u.%u.%u.in-addr.arpa.",
  519. (UCHAR) ((IpAddress & 0xff000000) >> 24),
  520. (UCHAR) ((IpAddress & 0x00ff0000) >> 16),
  521. (UCHAR) ((IpAddress & 0x0000ff00) >> 8),
  522. (UCHAR) (IpAddress & 0x000000ff) );
  523. return( pBuffer );
  524. }
  525. PCHAR
  526. Dns_Ip4AddressToReverseNameAlloc_A(
  527. IN IP_ADDRESS IpAddress
  528. )
  529. /*++
  530. Routine Description:
  531. Create reverse lookup name string, given corresponding IP.
  532. Caller must free the string.
  533. Arguments:
  534. IpAddress -- IP address to create
  535. Return Value:
  536. Ptr to new reverse lookup string.
  537. --*/
  538. {
  539. PCHAR pch;
  540. PCHAR pchend;
  541. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseNameAlloc_A()\n" ));
  542. //
  543. // allocate space for string
  544. //
  545. pch = ALLOCATE_HEAP( DNS_MAX_REVERSE_NAME_BUFFER_LENGTH );
  546. if ( !pch )
  547. {
  548. return( NULL );
  549. }
  550. //
  551. // write string for IP
  552. //
  553. pchend = Dns_Ip4AddressToReverseName_A( pch, IpAddress );
  554. if ( !pchend )
  555. {
  556. FREE_HEAP( pch );
  557. return( NULL );
  558. }
  559. return( pch );
  560. }
  561. PWCHAR
  562. Dns_Ip4AddressToReverseNameAlloc_W(
  563. IN IP_ADDRESS IpAddress
  564. )
  565. /*++
  566. Routine Description:
  567. Create reverse lookup name string, given corresponding IP.
  568. Caller must free the string.
  569. Arguments:
  570. IpAddress -- IP address to create
  571. Return Value:
  572. Ptr to new reverse lookup string.
  573. --*/
  574. {
  575. PWCHAR pch;
  576. PWCHAR pchend;
  577. DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseNameAlloc_W()\n" ));
  578. //
  579. // allocate space for string
  580. //
  581. pch = ALLOCATE_HEAP( DNS_MAX_REVERSE_NAME_BUFFER_LENGTH * sizeof(WCHAR) );
  582. if ( !pch )
  583. {
  584. return( NULL );
  585. }
  586. //
  587. // write string for IP
  588. //
  589. pchend = Dns_Ip4AddressToReverseName_W( pch, IpAddress );
  590. if ( !pchend )
  591. {
  592. FREE_HEAP( pch );
  593. return( NULL );
  594. }
  595. return( pch );
  596. }
  597. //
  598. // Reverse lookup address-to-name -- IP6
  599. //
  600. PCHAR
  601. Dns_Ip6AddressToReverseName_A(
  602. OUT PCHAR pBuffer,
  603. IN IP6_ADDRESS Ip6Addr
  604. )
  605. /*++
  606. Routine Description:
  607. Write reverse lookup name, given corresponding IP6 address
  608. Arguments:
  609. pBuffer -- ptr to buffer for reverse lookup name;
  610. MUST contain at least DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH bytes
  611. Ip6Addr -- IP6 address to create reverse string for
  612. Return Value:
  613. Ptr to next location in buffer.
  614. --*/
  615. {
  616. DWORD i;
  617. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseName_A()\n" ));
  618. //
  619. // write digit for each nibble in IP6 address
  620. //
  621. // note we are reversing net order here
  622. // since address is in net order and we are filling
  623. // in least to most significant order
  624. // - go DOWN through DWORDS
  625. // - go DOWN through the BYTES
  626. // - but we must put the lowest (least significant) nibble
  627. // first as our bits are not in "bit net order"
  628. // which is sending the highest bit in the byte first
  629. //
  630. #if 0
  631. i = 4;
  632. while ( i-- )
  633. {
  634. DWORD thisDword = Ip6Address.IP6Dword[i];
  635. pBuffer += sprintf(
  636. pBuffer,
  637. "%u.%u.%u.%u.%u.%u.%u.%u.",
  638. (thisDword & 0x0f000000) >> 24,
  639. (thisDword & 0xf0000000) >> 28,
  640. (thisDword & 0x000f0000) >> 16,
  641. (thisDword & 0x00f00000) >> 20,
  642. (thisDword & 0x00000f00) >> 8,
  643. (thisDword & 0x0000f000) >> 12,
  644. (thisDword & 0x0000000f) ,
  645. (thisDword & 0x000000f0) >> 4
  646. );
  647. }
  648. #endif
  649. i = 16;
  650. while ( i-- )
  651. {
  652. BYTE thisByte = Ip6Addr.IP6Byte[i];
  653. pBuffer += sprintf(
  654. pBuffer,
  655. "%x.%x.",
  656. (thisByte & 0x0f),
  657. (thisByte & 0xf0) >> 4
  658. );
  659. }
  660. pBuffer += sprintf(
  661. pBuffer,
  662. "ip6.int." );
  663. return( pBuffer );
  664. }
  665. PWCHAR
  666. Dns_Ip6AddressToReverseName_W(
  667. OUT PWCHAR pBuffer,
  668. IN IP6_ADDRESS Ip6Addr
  669. )
  670. /*++
  671. Routine Description:
  672. Write reverse lookup name, given corresponding IP6 address
  673. Arguments:
  674. pBuffer -- ptr to buffer for reverse lookup name;
  675. MUST contain at least DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH wide chars
  676. Ip6Addr -- IP6 address to create reverse string for
  677. Return Value:
  678. Ptr to next location in buffer.
  679. --*/
  680. {
  681. DWORD i;
  682. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseName_W()\n" ));
  683. //
  684. // write digit for each nibble in IP6 address
  685. // - in net order so lowest nibble is in highest memory
  686. //
  687. i = 16;
  688. while ( i-- )
  689. {
  690. BYTE thisByte = Ip6Addr.IP6Byte[i];
  691. pBuffer += wsprintfW(
  692. pBuffer,
  693. L"%x.%x.",
  694. (thisByte & 0x0f),
  695. (thisByte & 0xf0) >> 4
  696. );
  697. }
  698. pBuffer += wsprintfW(
  699. pBuffer,
  700. L"ip6.int." );
  701. return( pBuffer );
  702. }
  703. PCHAR
  704. Dns_Ip6AddressToReverseNameAlloc_A(
  705. IN IP6_ADDRESS Ip6Addr
  706. )
  707. /*++
  708. Routine Description:
  709. Create reverse lookup name given corresponding IP.
  710. Caller must free the string.
  711. Arguments:
  712. Ip6Addr -- IP6 address to create reverse name for
  713. Return Value:
  714. Ptr to new reverse lookup name string.
  715. --*/
  716. {
  717. PCHAR pch;
  718. PCHAR pchend;
  719. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseNameAlloc_A()\n" ));
  720. //
  721. // allocate space for string
  722. //
  723. pch = ALLOCATE_HEAP( DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH );
  724. if ( !pch )
  725. {
  726. return( NULL );
  727. }
  728. //
  729. // write string for IP
  730. //
  731. pchend = Dns_Ip6AddressToReverseName_A( pch, Ip6Addr );
  732. if ( !pchend )
  733. {
  734. FREE_HEAP( pch );
  735. return( NULL );
  736. }
  737. return( pch );
  738. }
  739. PWCHAR
  740. Dns_Ip6AddressToReverseNameAlloc_W(
  741. IN IP6_ADDRESS Ip6Addr
  742. )
  743. /*++
  744. Routine Description:
  745. Create reverse lookup name given corresponding IP.
  746. Caller must free the string.
  747. Arguments:
  748. Ip6Addr -- IP6 address to create reverse name for
  749. Return Value:
  750. Ptr to new reverse lookup name string.
  751. --*/
  752. {
  753. PWCHAR pch;
  754. PWCHAR pchend;
  755. DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseNameAlloc_W()\n" ));
  756. //
  757. // allocate space for string
  758. //
  759. pch = (PWCHAR) ALLOCATE_HEAP(
  760. DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH * sizeof(WCHAR) );
  761. if ( !pch )
  762. {
  763. return( NULL );
  764. }
  765. //
  766. // write string for IP
  767. //
  768. pchend = Dns_Ip6AddressToReverseName_W( pch, Ip6Addr );
  769. if ( !pchend )
  770. {
  771. FREE_HEAP( pch );
  772. return( NULL );
  773. }
  774. return( pch );
  775. }
  776. //
  777. // Reverse name-to-address -- IP4
  778. //
  779. BOOL
  780. Dns_Ip4ReverseNameToAddress_A(
  781. OUT PIP4_ADDRESS pIp4Addr,
  782. IN PCSTR pszName
  783. )
  784. /*++
  785. Routine Description:
  786. Get IP for reverse lookup name.
  787. Arguments:
  788. pIp4Addr -- addr to receive IP address if found
  789. pszName -- name to lookup
  790. Return Value:
  791. TRUE -- if reverse lookup name converted to IP
  792. FALSE -- if not IP4 reverse lookup name
  793. --*/
  794. {
  795. #define SIZE_IP4REV (sizeof(".in-addr.arpa")-1)
  796. CHAR nameBuffer[ DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH+1 ];
  797. DWORD nameLength;
  798. IP_ADDRESS ip;
  799. PCHAR pch;
  800. DWORD i;
  801. DWORD byte;
  802. DNSDBG( TRACE, (
  803. "Dns_Ip4ReverseNameToAddress_A( %s )\n",
  804. pszName ));
  805. //
  806. // validate name
  807. // fail if
  808. // - too long
  809. // - too short
  810. // - not in in-addr.arpa domain
  811. //
  812. nameLength = strlen( pszName );
  813. if ( nameLength > DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH )
  814. {
  815. return( FALSE );
  816. }
  817. if ( pszName[nameLength-1] == '.' )
  818. {
  819. nameLength--;
  820. }
  821. if ( nameLength <= SIZE_IP4REV )
  822. {
  823. return( FALSE );
  824. }
  825. nameLength -= SIZE_IP4REV;
  826. if ( _strnicmp( ".in-addr.arpa", &pszName[nameLength], SIZE_IP4REV ) != 0 )
  827. {
  828. return( FALSE );
  829. }
  830. //
  831. // copy reverse dotted decimal piece of name
  832. //
  833. RtlCopyMemory(
  834. nameBuffer,
  835. pszName,
  836. nameLength );
  837. nameBuffer[nameLength] = 0;
  838. //
  839. // read digits
  840. //
  841. ip = 0;
  842. i = 0;
  843. pch = nameBuffer + nameLength;
  844. while ( 1 )
  845. {
  846. --pch;
  847. if ( *pch == '.' )
  848. {
  849. *pch = 0;
  850. pch++;
  851. }
  852. else if ( pch == nameBuffer )
  853. {
  854. }
  855. else
  856. {
  857. continue;
  858. }
  859. // convert byte
  860. byte = strtoul( pch, NULL, 10 );
  861. if ( byte > 255 )
  862. {
  863. return( FALSE );
  864. }
  865. if ( i > 3 )
  866. {
  867. return( FALSE );
  868. }
  869. ip |= byte << (8*i);
  870. // terminate at string beginning
  871. // or continue back up string
  872. if ( pch == nameBuffer )
  873. {
  874. break;
  875. }
  876. i++;
  877. pch--;
  878. }
  879. *pIp4Addr = ip;
  880. DNSDBG( TRACE, (
  881. "Success on Dns_Ip4ReverseNameToAddress_A( %s ) => %s\n",
  882. pszName,
  883. IP_STRING(ip) ));
  884. return( TRUE );
  885. }
  886. BOOL
  887. Dns_Ip4ReverseNameToAddress_W(
  888. OUT PIP4_ADDRESS pIp4Addr,
  889. IN PCWSTR pwsName
  890. )
  891. /*++
  892. Routine Description:
  893. Get IP for reverse lookup name.
  894. Arguments:
  895. pIp4Addr -- addr to receive IP address if found
  896. pszName -- name to lookup
  897. Return Value:
  898. TRUE -- if reverse lookup name converted to IP
  899. FALSE -- if not IP4 reverse lookup name
  900. --*/
  901. {
  902. CHAR nameBuffer[ DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH+1 ];
  903. DWORD bufLength;
  904. DWORD nameLengthUtf8;
  905. DNSDBG( TRACE, (
  906. "Dns_Ip4ReverseNameToAddress_W( %S )\n",
  907. pwsName ));
  908. //
  909. // convert to UTF8
  910. // - use UTF8 since conversion to it is trivial and it
  911. // is identical to ANSI for all reverse lookup names
  912. //
  913. bufLength = DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH + 1;
  914. nameLengthUtf8 = Dns_StringCopy(
  915. nameBuffer,
  916. & bufLength,
  917. (PCHAR) pwsName,
  918. 0, // NULL terminated
  919. DnsCharSetUnicode,
  920. DnsCharSetUtf8 );
  921. if ( nameLengthUtf8 == 0 )
  922. {
  923. return FALSE;
  924. }
  925. //
  926. // call ANSI routine to do conversion
  927. //
  928. return Dns_Ip4ReverseNameToAddress_A(
  929. pIp4Addr,
  930. (PCSTR) nameBuffer );
  931. }
  932. //
  933. // Reverse name-to-address -- IP6
  934. //
  935. BOOL
  936. Dns_Ip6ReverseNameToAddress_A(
  937. OUT PIP6_ADDRESS pIp6Addr,
  938. IN PCSTR pszName
  939. )
  940. /*++
  941. Routine Description:
  942. Get IP6 address for reverse lookup name.
  943. Arguments:
  944. pIp6Addr -- addr to receive IP address if found
  945. pszName -- name to lookup
  946. Return Value:
  947. TRUE -- if reverse lookup name converted to IP
  948. FALSE -- if not IP4 reverse lookup name
  949. --*/
  950. {
  951. #define SIZE_IP6REV (sizeof(".ip6.int")-1)
  952. CHAR nameBuffer[ DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH+1 ];
  953. DWORD nameLength;
  954. PCHAR pch;
  955. BYTE byteArray[16];
  956. DWORD byteCount;
  957. DWORD nibble;
  958. DWORD highNibble;
  959. BOOL fisLow;
  960. DNSDBG( TRACE, ( "Dns_Ip6ReverseNameToAddress_A()\n" ));
  961. //
  962. // validate name
  963. // fail if
  964. // - too long
  965. // - too short
  966. // - not in in6.int domain
  967. //
  968. nameLength = strlen( pszName );
  969. if ( nameLength > DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH )
  970. {
  971. return( FALSE );
  972. }
  973. if ( pszName[nameLength-1] == '.' )
  974. {
  975. nameLength--;
  976. }
  977. if ( nameLength <= SIZE_IP6REV )
  978. {
  979. return( FALSE );
  980. }
  981. nameLength -= SIZE_IP6REV;
  982. if ( _strnicmp( ".ip6.int", &pszName[nameLength], SIZE_IP6REV ) != 0 )
  983. {
  984. return( FALSE );
  985. }
  986. //
  987. // copy name
  988. //
  989. RtlCopyMemory(
  990. nameBuffer,
  991. pszName,
  992. nameLength );
  993. nameBuffer[nameLength] = 0;
  994. //
  995. // clear IP6 address
  996. // - need for partial reverse lookup name
  997. //
  998. RtlZeroMemory(
  999. byteArray,
  1000. sizeof(byteArray) );
  1001. //
  1002. // read digits
  1003. //
  1004. byteCount = 0;
  1005. fisLow = FALSE;
  1006. pch = nameBuffer + nameLength;
  1007. while ( 1 )
  1008. {
  1009. if ( byteCount > 15 )
  1010. {
  1011. return( FALSE );
  1012. }
  1013. --pch;
  1014. if ( *pch == '.' )
  1015. {
  1016. *pch = 0;
  1017. pch++;
  1018. }
  1019. else if ( pch == nameBuffer )
  1020. {
  1021. }
  1022. else
  1023. {
  1024. // DCR: multi-digit nibbles in reverse name -- error?
  1025. continue;
  1026. }
  1027. // convert nibble
  1028. // - zero test special as
  1029. // A) faster
  1030. // B) strtoul() uses for error case
  1031. if ( *pch == '0' )
  1032. {
  1033. nibble = 0;
  1034. }
  1035. else
  1036. {
  1037. nibble = strtoul( pch, NULL, 16 );
  1038. if ( nibble == 0 || nibble > 15 )
  1039. {
  1040. return( FALSE );
  1041. }
  1042. }
  1043. // save high nibble
  1044. // on low nibble, write byte to IP6 address
  1045. if ( !fisLow )
  1046. {
  1047. highNibble = nibble;
  1048. fisLow = TRUE;
  1049. }
  1050. else
  1051. {
  1052. //byteArray[byteCount++] = (BYTE) (lowNibble | (nibble << 4));
  1053. pIp6Addr->IP6Byte[byteCount++] = (BYTE) ( (highNibble<<4) | nibble );
  1054. fisLow = FALSE;
  1055. }
  1056. // terminate at string beginning
  1057. // or continue back up string
  1058. if ( pch == nameBuffer )
  1059. {
  1060. break;
  1061. }
  1062. pch--;
  1063. }
  1064. //*pIp6Addr = *(PIP6_ADDRESS) byteArray;
  1065. DNSDBG( TRACE, (
  1066. "Success on Dns_Ip6ReverseNameToAddress_A( %s )\n",
  1067. pszName ));
  1068. return( TRUE );
  1069. }
  1070. BOOL
  1071. Dns_Ip6ReverseNameToAddress_W(
  1072. OUT PIP6_ADDRESS pIp6Addr,
  1073. IN PCWSTR pwsName
  1074. )
  1075. /*++
  1076. Routine Description:
  1077. Get IP for reverse lookup name.
  1078. Arguments:
  1079. pIp6Addr -- addr to receive IP address if found
  1080. pszName -- name to lookup
  1081. Return Value:
  1082. TRUE -- if reverse lookup name converted to IP
  1083. FALSE -- if not IP6 reverse lookup name
  1084. --*/
  1085. {
  1086. CHAR nameBuffer[ DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH+1 ];
  1087. DWORD bufLength;
  1088. DWORD nameLengthUtf8;
  1089. DNSDBG( TRACE, (
  1090. "Dns_Ip6ReverseNameToAddress_W( %S )\n",
  1091. pwsName ));
  1092. //
  1093. // convert to UTF8
  1094. // - use UTF8 since conversion to it is trivial and it
  1095. // is identical to ANSI for all reverse lookup names
  1096. //
  1097. bufLength = DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH + 1;
  1098. nameLengthUtf8 = Dns_StringCopy(
  1099. nameBuffer,
  1100. & bufLength,
  1101. (PCHAR) pwsName,
  1102. 0, // NULL terminated
  1103. DnsCharSetUnicode,
  1104. DnsCharSetUtf8 );
  1105. if ( nameLengthUtf8 == 0 )
  1106. {
  1107. return FALSE;
  1108. }
  1109. //
  1110. // call ANSI routine to do conversion
  1111. //
  1112. return Dns_Ip6ReverseNameToAddress_A(
  1113. pIp6Addr,
  1114. (PCSTR) nameBuffer );
  1115. }
  1116. //
  1117. // Combined IP4/IP6 reverse-name-to-address
  1118. //
  1119. BOOL
  1120. Dns_ReverseNameToAddress_W(
  1121. OUT PCHAR pAddrBuf,
  1122. IN OUT PDWORD pBufLength,
  1123. IN PCWSTR pString,
  1124. IN OUT PDWORD pAddrFamily
  1125. )
  1126. /*++
  1127. Routine Description:
  1128. Build address (IP4 or IP6) from reverse lookup name.
  1129. Arguments:
  1130. pAddrBuf -- buffer to receive address
  1131. pBufLength -- ptr to address length
  1132. input - length of buffer
  1133. output - length of address found
  1134. pString -- address string
  1135. pAddrFamily -- ptr to address family
  1136. input - zero for any family or particular family to check
  1137. output - family found; zero if no conversion
  1138. Return Value:
  1139. TRUE if successful.
  1140. FALSE on error. GetLastError() for status.
  1141. --*/
  1142. {
  1143. return Dns_StringToAddressEx(
  1144. pAddrBuf,
  1145. pBufLength,
  1146. (PCSTR) pString,
  1147. pAddrFamily,
  1148. TRUE, // unicode
  1149. TRUE // reverse
  1150. );
  1151. }
  1152. BOOL
  1153. Dns_ReverseNameToAddress_A(
  1154. OUT PCHAR pAddrBuf,
  1155. IN OUT PDWORD pBufLength,
  1156. IN PCSTR pString,
  1157. IN OUT PDWORD pAddrFamily
  1158. )
  1159. {
  1160. return Dns_StringToAddressEx(
  1161. pAddrBuf,
  1162. pBufLength,
  1163. pString,
  1164. pAddrFamily,
  1165. FALSE, // ANSI
  1166. TRUE // reverse
  1167. );
  1168. }
  1169. //
  1170. // Combined string-to-address private workhorse
  1171. //
  1172. BOOL
  1173. Dns_StringToAddressEx(
  1174. OUT PCHAR pAddrBuf,
  1175. IN OUT PDWORD pBufLength,
  1176. IN PCSTR pString,
  1177. IN OUT PDWORD pAddrFamily,
  1178. IN BOOL fUnicode,
  1179. IN BOOL fReverse
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. Build address (IP4 or IP6 from string)
  1184. This routine is capable of all string-to-address
  1185. conversions and is the backbone of all the
  1186. combined string-to-address conversion routines.
  1187. Arguments:
  1188. pAddrBuf -- buffer to receive address
  1189. pBufLength -- ptr to address length
  1190. input - length of buffer
  1191. output - length of address found
  1192. pString -- address string
  1193. pAddrFamily -- ptr to address family
  1194. input - zero for any family or particular family to check
  1195. output - family found; zero if no conversion
  1196. fUnicode -- unicode string
  1197. fReverse -- reverse lookup string
  1198. Return Value:
  1199. TRUE if successful.
  1200. FALSE on error.
  1201. --*/
  1202. {
  1203. DNS_STATUS status = NO_ERROR;
  1204. DWORD length = 0;
  1205. INT family = *pAddrFamily;
  1206. DWORD bufLength = *pBufLength;
  1207. BOOL fconvert;
  1208. PCSTR preverseString;
  1209. CHAR nameBuffer[ DNS_MAX_REVERSE_NAME_BUFFER_LENGTH+1 ];
  1210. DNSDBG( TRACE, (
  1211. "Dns_StringToAddressEx( %S%s )\n",
  1212. fUnicode ? pString : "",
  1213. fUnicode ? "" : pString ));
  1214. //
  1215. // convert reverse to ANSI
  1216. //
  1217. // reverse lookups are done in ANSI; convert here to avoid
  1218. // double string conversion to check both IP4 and IP6
  1219. //
  1220. if ( fReverse )
  1221. {
  1222. preverseString = pString;
  1223. if ( fUnicode )
  1224. {
  1225. DWORD bufLength = DNS_MAX_REVERSE_NAME_BUFFER_LENGTH;
  1226. if ( ! Dns_StringCopy(
  1227. nameBuffer,
  1228. & bufLength,
  1229. (PCHAR) pString,
  1230. 0, // NULL terminated
  1231. DnsCharSetUnicode,
  1232. DnsCharSetUtf8 ) )
  1233. {
  1234. return FALSE;
  1235. }
  1236. preverseString = nameBuffer;
  1237. }
  1238. }
  1239. //
  1240. // check IP4
  1241. //
  1242. if ( family == 0 ||
  1243. family == AF_INET )
  1244. {
  1245. IP4_ADDRESS ip;
  1246. if ( fReverse )
  1247. {
  1248. fconvert = Dns_Ip4ReverseNameToAddress_A(
  1249. & ip,
  1250. preverseString );
  1251. }
  1252. else
  1253. {
  1254. if ( fUnicode )
  1255. {
  1256. fconvert = Dns_Ip4StringToAddress_W(
  1257. & ip,
  1258. (PCWSTR)pString );
  1259. }
  1260. else
  1261. {
  1262. fconvert = Dns_Ip4StringToAddress_A(
  1263. & ip,
  1264. pString );
  1265. }
  1266. }
  1267. if ( fconvert )
  1268. {
  1269. length = sizeof(IP4_ADDRESS);
  1270. family = AF_INET;
  1271. if ( bufLength < length )
  1272. {
  1273. status = ERROR_MORE_DATA;
  1274. }
  1275. else
  1276. {
  1277. * (PIP4_ADDRESS) pAddrBuf = ip;
  1278. }
  1279. DNSDBG( INIT2, (
  1280. "Converted string to IP4 address %s\n",
  1281. IP_STRING(ip) ));
  1282. goto Done;
  1283. }
  1284. }
  1285. //
  1286. // check IP6
  1287. //
  1288. if ( family == 0 ||
  1289. family == AF_INET6 )
  1290. {
  1291. IP6_ADDRESS ip;
  1292. if ( fReverse )
  1293. {
  1294. fconvert = Dns_Ip6ReverseNameToAddress_A(
  1295. & ip,
  1296. preverseString );
  1297. }
  1298. else
  1299. {
  1300. if ( fUnicode )
  1301. {
  1302. fconvert = Dns_Ip6StringToAddress_W(
  1303. & ip,
  1304. (PCWSTR)pString );
  1305. }
  1306. else
  1307. {
  1308. fconvert = Dns_Ip6StringToAddress_A(
  1309. & ip,
  1310. pString );
  1311. }
  1312. }
  1313. if ( fconvert )
  1314. {
  1315. length = sizeof(IP6_ADDRESS);
  1316. if ( bufLength < length )
  1317. {
  1318. status = ERROR_MORE_DATA;
  1319. }
  1320. else
  1321. {
  1322. family = AF_INET6;
  1323. * (PIP6_ADDRESS) pAddrBuf = ip;
  1324. }
  1325. IF_DNSDBG( INIT2 )
  1326. {
  1327. DnsDbg_Ip6Address(
  1328. "Converted string to IP6 address: ",
  1329. (PIP6_ADDRESS) pAddrBuf,
  1330. "\n" );
  1331. }
  1332. goto Done;
  1333. }
  1334. }
  1335. length = 0;
  1336. family = 0;
  1337. status = DNS_ERROR_INVALID_IP_ADDRESS;
  1338. Done:
  1339. if ( status )
  1340. {
  1341. SetLastError( status );
  1342. }
  1343. *pAddrFamily = family;
  1344. *pBufLength = length;
  1345. DNSDBG( TRACE, (
  1346. "Leave Dns_StringToAddressEx()\n"
  1347. "\tstatus = %d\n"
  1348. "\tptr = %p\n"
  1349. "\tlength = %d\n"
  1350. "\tfamily = %d\n",
  1351. status,
  1352. pAddrBuf,
  1353. length,
  1354. family ));
  1355. return( status==ERROR_SUCCESS );
  1356. }
  1357. //
  1358. // End straddr.c
  1359. //