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.

800 lines
21 KiB

  1. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  2. /*---------------------------------------------------------
  3. Filename: address.cpp
  4. Written By: B.Rajeev
  5. ----------------------------------------------------------*/
  6. #include "precomp.h"
  7. #include "common.h"
  8. #include "address.h"
  9. #include <winsock.h>
  10. #include <iomanip.h>
  11. // this character separates the field values in a dot-notation representation
  12. #define FIELD_SEPARATOR '.'
  13. #define IPX_FIELD_SEPARATOR ':'
  14. SnmpTransportIpAddress::SnmpTransportIpAddress ( IN const UCHAR *address, IN const USHORT address_length )
  15. {
  16. allocated = FALSE;
  17. is_valid = FALSE;
  18. if ( address_length != SNMP_IP_ADDR_LEN )
  19. return;
  20. is_valid = TRUE;
  21. for ( ULONG index = 0 ; index < SNMP_IP_ADDR_LEN ; index ++ )
  22. {
  23. field [ index ] = address [ index ] ;
  24. }
  25. }
  26. // sets the fields to the contents extracted from the dotted
  27. // decimal address string in parameter
  28. SnmpTransportIpAddress::SnmpTransportIpAddress ( IN const char *address , IN const ULONG addressResolution )
  29. {
  30. allocated = FALSE;
  31. is_valid = FALSE;
  32. if ( addressResolution & SNMP_ADDRESS_RESOLVE_VALUE )
  33. {
  34. is_valid = GetIpAddress ( address ) ;
  35. if ( is_valid == FALSE )
  36. {
  37. // Try GetHostByName
  38. if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
  39. {
  40. hostent FAR *hostEntry = gethostbyname ( address );
  41. if ( hostEntry )
  42. {
  43. is_valid = TRUE ;
  44. field [ 0 ] = ( UCHAR ) hostEntry->h_addr [ 0 ] ;
  45. field [ 1 ] = ( UCHAR ) hostEntry->h_addr [ 1 ] ;
  46. field [ 2 ] = ( UCHAR ) hostEntry->h_addr [ 2 ] ;
  47. field [ 3 ] = ( UCHAR ) hostEntry->h_addr [ 3 ] ;
  48. }
  49. }
  50. }
  51. }
  52. else if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
  53. {
  54. hostent FAR *hostEntry = gethostbyname ( address );
  55. if ( hostEntry )
  56. {
  57. is_valid = TRUE ;
  58. field [ 0 ] = ( UCHAR ) hostEntry->h_addr [ 0 ] ;
  59. field [ 1 ] = ( UCHAR ) hostEntry->h_addr [ 1 ] ;
  60. field [ 2 ] = ( UCHAR ) hostEntry->h_addr [ 2 ] ;
  61. field [ 3 ] = ( UCHAR ) hostEntry->h_addr [ 3 ] ;
  62. }
  63. }
  64. }
  65. BOOL SnmpTransportIpAddress::ValidateAddress ( IN const char *address , IN const ULONG addressResolution )
  66. {
  67. BOOL is_valid = FALSE ;
  68. if ( addressResolution & SNMP_ADDRESS_RESOLVE_VALUE )
  69. {
  70. // create a stream to read the fields from
  71. istrstream address_stream((char *)address);
  72. // contains the maximum value for a USHORT. used
  73. // for comparison with the field values read
  74. const UCHAR max_uchar = -1;
  75. // consecutive fields must be separated by a
  76. // FIELD_SEPARATOR
  77. char separator;
  78. // a field is first read into this for comparison
  79. // with max_uchar
  80. ULONG temp_field;
  81. // read the first three (USHORT,FIELD_SEPARATOR) pairs
  82. // check if the stream is good before each read
  83. for(int i=0; i < (SNMP_IP_ADDR_LEN-1); i++)
  84. {
  85. if ( !address_stream.good() )
  86. break;
  87. address_stream >> temp_field;
  88. if ( temp_field > max_uchar )
  89. {
  90. address_stream.clear ( ios :: badbit ) ;
  91. break;
  92. }
  93. if ( !address_stream.good() )
  94. break;
  95. address_stream >> separator;
  96. if ( separator != FIELD_SEPARATOR )
  97. {
  98. address_stream.clear ( ios :: badbit ) ;
  99. break;
  100. }
  101. }
  102. if ( address_stream.good() )
  103. {
  104. address_stream >> temp_field;
  105. if (temp_field <= max_uchar)
  106. {
  107. // make sure that there are is nothing more left in the
  108. // stream
  109. if ( address_stream.eof() )
  110. {
  111. is_valid = TRUE;
  112. }
  113. }
  114. }
  115. if ( ! is_valid )
  116. {
  117. if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
  118. {
  119. hostent FAR *hostEntry = gethostbyname ( address );
  120. if ( hostEntry )
  121. {
  122. is_valid = TRUE ;
  123. }
  124. }
  125. }
  126. }
  127. else
  128. {
  129. if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
  130. {
  131. hostent FAR *hostEntry = gethostbyname ( address );
  132. if ( hostEntry )
  133. {
  134. is_valid = TRUE ;
  135. }
  136. }
  137. }
  138. return is_valid ;
  139. }
  140. BOOL SnmpTransportIpAddress::GetIpAddress ( IN const char *address )
  141. {
  142. // create a stream to read the fields from
  143. istrstream address_stream((char *)address);
  144. // contains the maximum value for a USHORT. used
  145. // for comparison with the field values read
  146. const UCHAR max_uchar = -1;
  147. // consecutive fields must be separated by a
  148. // FIELD_SEPARATOR
  149. char separator;
  150. // a field is first read into this for comparison
  151. // with max_uchar
  152. ULONG temp_field;
  153. is_valid = FALSE;
  154. // read the first three (USHORT,FIELD_SEPARATOR) pairs
  155. // check if the stream is good before each read
  156. for(int i=0; i < (SNMP_IP_ADDR_LEN-1); i++)
  157. {
  158. if ( !address_stream.good() )
  159. break;
  160. address_stream >> temp_field;
  161. if ( temp_field > max_uchar )
  162. {
  163. address_stream.clear ( ios :: badbit ) ;
  164. break;
  165. }
  166. field[i] = (UCHAR)temp_field;
  167. if ( !address_stream.good() )
  168. break;
  169. address_stream >> separator;
  170. if ( separator != FIELD_SEPARATOR )
  171. {
  172. address_stream.clear ( ios :: badbit ) ;
  173. break;
  174. }
  175. }
  176. if ( address_stream.good() )
  177. {
  178. address_stream >> temp_field;
  179. if (temp_field <= max_uchar)
  180. {
  181. field[SNMP_IP_ADDR_LEN-1] = (UCHAR)temp_field;
  182. // make sure that there are is nothing more left in the
  183. // stream
  184. if ( address_stream.eof() )
  185. {
  186. is_valid = TRUE;
  187. }
  188. }
  189. }
  190. return is_valid ;
  191. }
  192. // set the fields to the lower 32 bits in the ULONG parameter
  193. // in general, sets the SNMP_IP_ADDR_LEN fields, each of size 8 bits
  194. #pragma warning (disable:4244)
  195. SnmpTransportIpAddress::SnmpTransportIpAddress( IN const ULONG address )
  196. {
  197. allocated = FALSE;
  198. // flag starts with the last byte on
  199. ULONG hostOrder = ntohl ( address ) ;
  200. field [ 0 ] = ( hostOrder >> 24 ) & 0xff ;
  201. field [ 1 ] = ( hostOrder >> 16 ) & 0xff ;
  202. field [ 2 ] = ( hostOrder >> 8 ) & 0xff ;
  203. field [ 3 ] = hostOrder & 0xff ;
  204. is_valid = TRUE;
  205. }
  206. #pragma warning (default:4244)
  207. // free the dotted notation string if it was allocated
  208. SnmpTransportIpAddress::~SnmpTransportIpAddress()
  209. {
  210. if ( allocated )
  211. delete[] dotted_notation;
  212. }
  213. // returns the number of fields copied
  214. USHORT SnmpTransportIpAddress::GetAddress ( OUT UCHAR *address , IN const USHORT length ) const
  215. {
  216. // if the stream is valid, copy the fields onto the
  217. // buffer pointed to by address.
  218. if ( is_valid )
  219. {
  220. // only these many fields need be copied
  221. USHORT len = MIN(length,SNMP_IP_ADDR_LEN);
  222. for(int i=0; i < len; i++)
  223. address[i] = field[i];
  224. return len;
  225. }
  226. else
  227. return 0;
  228. }
  229. // prepares a dot-notation representation of the address and points
  230. // the dotted_notation char ptr to the allocated string.
  231. // Note: memory for the decimal notation string is allocated only when
  232. // the char *GetAddress method is called (and the address is valid)
  233. // this memory must be freed if required
  234. char *SnmpTransportIpAddress::GetAddress()
  235. {
  236. // do all this only when the address is valid
  237. if ( is_valid )
  238. {
  239. // if already allocated, return the stored string
  240. if ( allocated )
  241. return dotted_notation;
  242. else
  243. {
  244. // create a temp. output stream to prepare the char string
  245. dotted_notation = new char[ MAX_ADDRESS_LEN ];
  246. allocated = TRUE;
  247. sprintf (
  248. dotted_notation,
  249. "%d.%d.%d.%d" ,
  250. (ULONG)field[0],
  251. (ULONG)field[1],
  252. (ULONG)field[2],
  253. (ULONG)field[3]
  254. );
  255. return dotted_notation;
  256. }
  257. }
  258. else
  259. return NULL;
  260. }
  261. SnmpTransportAddress *SnmpTransportIpAddress::Copy () const
  262. {
  263. SnmpTransportIpAddress *new_address = new SnmpTransportIpAddress();
  264. if ( is_valid )
  265. *new_address = field;
  266. return new_address;
  267. }
  268. // checks if the two instances represent equal addresses
  269. BOOL SnmpTransportIpAddress::operator== ( IN const SnmpTransportIpAddress & address ) const
  270. {
  271. // if both the instances are valid, then a field
  272. // by field comparison, starting with the most
  273. // significant field (index 0) yields the answer
  274. if ( (is_valid) && address.IsValid() )
  275. {
  276. UCHAR temp[SNMP_IP_ADDR_LEN];
  277. address.GetAddress(temp,SNMP_IP_ADDR_LEN);
  278. for(int i=0; i < SNMP_IP_ADDR_LEN; i++)
  279. if ( field[i] != temp[i] )
  280. return FALSE;
  281. return TRUE;
  282. }
  283. else // if either of them is invalid, they
  284. // cannot be equal
  285. return FALSE;
  286. }
  287. // sets the internal address to the specified parameter
  288. // and makes the instance valid
  289. SnmpTransportIpAddress &SnmpTransportIpAddress::operator= ( IN const UCHAR *ipAddr )
  290. {
  291. if ( ipAddr == NULL )
  292. return *this;
  293. const UCHAR max_uchar = -1;
  294. for(int i=0; i < SNMP_IP_ADDR_LEN; i++)
  295. {
  296. if ( ipAddr[i] > max_uchar )
  297. return *this;
  298. field[i] = ipAddr[i];
  299. }
  300. is_valid = TRUE;
  301. // if a dotted-notation char string was prepared for the previous address
  302. // free the allocated memory
  303. if ( allocated )
  304. {
  305. delete[] dotted_notation;
  306. allocated = FALSE;
  307. }
  308. return *this;
  309. }
  310. // copies the specified instance (parameter) onto itself
  311. // if the parameter instance is found valid
  312. SnmpTransportIpAddress &SnmpTransportIpAddress::operator= ( IN const SnmpTransportIpAddress &address )
  313. {
  314. const UCHAR max_uchar = -1;
  315. // if valid, proceed
  316. if (address.IsValid())
  317. {
  318. // get address fields
  319. address.GetAddress(field,SNMP_IP_ADDR_LEN);
  320. // copy the obtained fields onto local fields
  321. for( int i=0; i < SNMP_IP_ADDR_LEN; i++ )
  322. if ( field[i] > max_uchar )
  323. return *this;
  324. is_valid = TRUE;
  325. // since the address changes, free the previously
  326. // allocated dotted-notation char string
  327. if ( allocated )
  328. {
  329. delete[] dotted_notation;
  330. allocated = FALSE;
  331. }
  332. }
  333. return *this;
  334. }
  335. // returns the field requested by the parameter index
  336. // if the index is illegal, an OutOfRange exception is
  337. // raised
  338. UCHAR SnmpTransportIpAddress::operator[] ( IN const USHORT index ) const
  339. {
  340. // if valid and the index is legal, return the field
  341. if ( (is_valid) && (BETWEEN(index,0,SNMP_IP_ADDR_LEN)) )
  342. return field[index];
  343. // should never reach here if the caller checked the index
  344. return 0;
  345. }
  346. SnmpTransportIpxAddress::SnmpTransportIpxAddress ( IN const UCHAR *address, IN const USHORT address_length )
  347. {
  348. allocated = FALSE;
  349. is_valid = FALSE;
  350. if ( address_length != SNMP_IPX_ADDR_LEN )
  351. return;
  352. is_valid = TRUE;
  353. for ( ULONG index = 0 ; index < SNMP_IPX_ADDR_LEN ; index ++ )
  354. {
  355. field [ index ] = address [ index ] ;
  356. }
  357. }
  358. // sets the fields to the contents extracted from the dotted
  359. // decimal address string in parameter
  360. SnmpTransportIpxAddress::SnmpTransportIpxAddress ( IN const char *address )
  361. {
  362. allocated = FALSE;
  363. is_valid = GetIpxAddress ( address ) ;
  364. }
  365. UCHAR HexToDecInteger ( char token )
  366. {
  367. if ( token >= '0' && token <= '9' )
  368. {
  369. return token - '0' ;
  370. }
  371. else if ( token >= 'a' && token <= 'f' )
  372. {
  373. return token - 'a' + 10 ;
  374. }
  375. else if ( token >= 'A' && token <= 'F' )
  376. {
  377. return token - 'A' + 10 ;
  378. }
  379. else
  380. {
  381. return 0 ;
  382. }
  383. }
  384. #pragma warning (disable:4244)
  385. BOOL SnmpTransportIpxAddress::ValidateAddress ( IN const char *address )
  386. {
  387. BOOL is_valid = TRUE ;
  388. // create a stream to read the fields from
  389. istrstream address_stream((char *)address);
  390. address_stream.setf ( ios :: hex ) ;
  391. ULONG t_NetworkAddress ;
  392. address_stream >> t_NetworkAddress ;
  393. if ( address_stream.good() )
  394. {
  395. // consecutive fields must be separated by a
  396. // FIELD_SEPARATOR
  397. char separator;
  398. address_stream >> separator;
  399. if ( separator == IPX_FIELD_SEPARATOR )
  400. {
  401. ULONG t_StationOctets = 0 ;
  402. while ( is_valid && t_StationOctets < 6 )
  403. {
  404. int t_OctetHigh = address_stream.get () ;
  405. int t_OctetLow = address_stream.get () ;
  406. if ( isxdigit ( t_OctetHigh ) && isxdigit ( t_OctetLow ) )
  407. {
  408. t_StationOctets ++ ;
  409. }
  410. else
  411. {
  412. is_valid = FALSE ;
  413. }
  414. }
  415. if ( t_StationOctets != 6 )
  416. {
  417. is_valid = FALSE ;
  418. }
  419. }
  420. if ( address_stream.eof() )
  421. {
  422. is_valid = TRUE;
  423. }
  424. }
  425. else
  426. {
  427. is_valid = FALSE ;
  428. }
  429. return is_valid ;
  430. }
  431. BOOL SnmpTransportIpxAddress::GetIpxAddress ( IN const char *address )
  432. {
  433. // create a stream to read the fields from
  434. istrstream address_stream((char *)address);
  435. address_stream.setf ( ios :: hex ) ;
  436. is_valid = TRUE ;
  437. ULONG t_NetworkAddress ;
  438. address_stream >> t_NetworkAddress ;
  439. if ( address_stream.good() )
  440. {
  441. field [ 0 ] = ( t_NetworkAddress >> 24 ) & 0xff ;
  442. field [ 1 ] = ( t_NetworkAddress >> 16 ) & 0xff ;
  443. field [ 2 ] = ( t_NetworkAddress >> 8 ) & 0xff ;
  444. field [ 3 ] = t_NetworkAddress & 0xff ;
  445. // consecutive fields must be separated by a
  446. // FIELD_SEPARATOR
  447. char separator;
  448. address_stream >> separator;
  449. if ( separator == IPX_FIELD_SEPARATOR )
  450. {
  451. ULONG t_StationOctets = 0 ;
  452. while ( is_valid && t_StationOctets < 6 )
  453. {
  454. int t_OctetHigh = address_stream.get () ;
  455. int t_OctetLow = address_stream.get () ;
  456. if ( isxdigit ( t_OctetHigh ) && isxdigit ( t_OctetLow ) )
  457. {
  458. UCHAR t_Octet = ( HexToDecInteger ( (char)t_OctetHigh ) << 4 ) + HexToDecInteger ( (char)t_OctetLow ) ;
  459. field [ 4 + t_StationOctets ] = t_Octet ;
  460. t_StationOctets ++ ;
  461. }
  462. else
  463. {
  464. is_valid = FALSE ;
  465. }
  466. }
  467. if ( t_StationOctets != 6 )
  468. {
  469. is_valid = FALSE ;
  470. }
  471. }
  472. if ( address_stream.eof() )
  473. {
  474. is_valid = TRUE;
  475. }
  476. }
  477. else
  478. {
  479. is_valid = FALSE ;
  480. }
  481. return is_valid ;
  482. }
  483. #pragma warning (default:4244)
  484. // free the dotted notation string if it was allocated
  485. SnmpTransportIpxAddress::~SnmpTransportIpxAddress()
  486. {
  487. if ( allocated )
  488. delete[] dotted_notation;
  489. }
  490. // returns the number of fields copied
  491. USHORT SnmpTransportIpxAddress::GetAddress ( OUT UCHAR *address , IN const USHORT length ) const
  492. {
  493. // if the stream is valid, copy the fields onto the
  494. // buffer pointed to by address.
  495. if ( is_valid )
  496. {
  497. // only these many fields need be copied
  498. USHORT len = MIN(length,SNMP_IPX_ADDR_LEN);
  499. for(int i=0; i < len; i++)
  500. address[i] = field[i];
  501. return len;
  502. }
  503. else
  504. return 0;
  505. }
  506. // prepares a dot-notation representation of the address and points
  507. // the dotted_notation char ptr to the allocated string.
  508. // Note: memory for the decimal notation string is allocated only when
  509. // the char *GetAddress method is called (and the address is valid)
  510. // this memory must be freed if required
  511. char *SnmpTransportIpxAddress::GetAddress()
  512. {
  513. // do all this only when the address is valid
  514. if ( is_valid )
  515. {
  516. // if already allocated, return the stored string
  517. if ( allocated )
  518. return dotted_notation;
  519. else
  520. {
  521. // create a temp. output stream to prepare the char string
  522. char temp[MAX_ADDRESS_LEN];
  523. ostrstream temp_stream(temp, MAX_ADDRESS_LEN);
  524. // if any problems with the stream return NULL
  525. if ( !temp_stream.good() )
  526. return NULL;
  527. temp_stream.setf ( ios :: hex ) ;
  528. temp_stream.width ( 8 ) ;
  529. temp_stream.fill ( '0' ) ;
  530. ULONG t_NetworkAddress = ( field [ 0 ] << 24 ) +
  531. ( field [ 1 ] << 16 ) +
  532. ( field [ 2 ] << 8 ) +
  533. ( field [ 3 ] ) ;
  534. // output the fields separated by the FIELD_SEPARATOR onto the output stream
  535. temp_stream << t_NetworkAddress << IPX_FIELD_SEPARATOR ;
  536. ;
  537. for(int i=SNMP_IPX_NETWORK_LEN; (temp_stream.good()) && (i < SNMP_IPX_ADDR_LEN); i++)
  538. {
  539. temp_stream.width ( 2 ) ;
  540. temp_stream << (ULONG)field[i];
  541. }
  542. // if any problems with the stream return NULL
  543. if ( !temp_stream.good() )
  544. return NULL;
  545. // end of string
  546. temp_stream << (char)EOS;
  547. // allocate the required memory and copy the prepared string onto it
  548. int len = strlen(temp);
  549. dotted_notation = new char[len+1];
  550. allocated = TRUE;
  551. strcpy(dotted_notation, temp);
  552. return dotted_notation;
  553. }
  554. }
  555. else
  556. return NULL;
  557. }
  558. SnmpTransportAddress *SnmpTransportIpxAddress::Copy () const
  559. {
  560. SnmpTransportIpxAddress *new_address = new SnmpTransportIpxAddress();
  561. if ( is_valid )
  562. *new_address = field;
  563. return new_address;
  564. }
  565. // checks if the two instances represent equal addresses
  566. BOOL SnmpTransportIpxAddress::operator== ( IN const SnmpTransportIpxAddress & address ) const
  567. {
  568. // if both the instances are valid, then a field
  569. // by field comparison, starting with the most
  570. // significant field (index 0) yields the answer
  571. if ( (is_valid) && address.IsValid() )
  572. {
  573. UCHAR temp[SNMP_IPX_ADDR_LEN];
  574. address.GetAddress(temp,SNMP_IPX_ADDR_LEN);
  575. for(int i=0; i < SNMP_IPX_ADDR_LEN; i++)
  576. if ( field[i] != temp[i] )
  577. return FALSE;
  578. return TRUE;
  579. }
  580. else // if either of them is invalid, they
  581. // cannot be equal
  582. return FALSE;
  583. }
  584. // sets the internal address to the specified parameter
  585. // and makes the instance valid
  586. SnmpTransportIpxAddress &SnmpTransportIpxAddress::operator= ( IN const UCHAR *ipAddr )
  587. {
  588. if ( ipAddr == NULL )
  589. return *this;
  590. const UCHAR max_uchar = -1;
  591. for(int i=0; i < SNMP_IPX_ADDR_LEN; i++)
  592. {
  593. if ( ipAddr[i] > max_uchar )
  594. return *this;
  595. field[i] = ipAddr[i];
  596. }
  597. is_valid = TRUE;
  598. // if a dotted-notation char string was prepared for the previous address
  599. // free the allocated memory
  600. if ( allocated )
  601. {
  602. delete[] dotted_notation;
  603. allocated = FALSE;
  604. }
  605. return *this;
  606. }
  607. // copies the specified instance (parameter) onto itself
  608. // if the parameter instance is found valid
  609. SnmpTransportIpxAddress &SnmpTransportIpxAddress::operator= ( IN const SnmpTransportIpxAddress &address )
  610. {
  611. const UCHAR max_uchar = -1;
  612. // if valid, proceed
  613. if (address.IsValid())
  614. {
  615. // get address fields
  616. address.GetAddress(field,SNMP_IPX_ADDR_LEN);
  617. // copy the obtained fields onto local fields
  618. for( int i=0; i < SNMP_IPX_ADDR_LEN; i++ )
  619. if ( field[i] > max_uchar )
  620. return *this;
  621. is_valid = TRUE;
  622. // since the address changes, free the previously
  623. // allocated dotted-notation char string
  624. if ( allocated )
  625. {
  626. delete[] dotted_notation;
  627. allocated = FALSE;
  628. }
  629. }
  630. return *this;
  631. }
  632. // returns the field requested by the parameter index
  633. // if the index is illegal, an OutOfRange exception is
  634. // raised
  635. UCHAR SnmpTransportIpxAddress::operator[] ( IN const USHORT index ) const
  636. {
  637. // if valid and the index is legal, return the field
  638. if ( (is_valid) && (BETWEEN(index,0,SNMP_IPX_ADDR_LEN)) )
  639. return field[index];
  640. // should never reach here if the caller checked the index
  641. return 0;
  642. }