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.

1086 lines
38 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: most of the rpc apis are here and some miscellaneous functions too
  5. // all the functions here go to the DS directly.
  6. //================================================================================
  7. #include <hdrmacro.h>
  8. #include <store.h>
  9. #include <dhcpmsg.h>
  10. #include <wchar.h>
  11. #include <dhcpbas.h>
  12. #include <mm\opt.h>
  13. #include <mm\optl.h>
  14. #include <mm\optdefl.h>
  15. #include <mm\optclass.h>
  16. #include <mm\classdefl.h>
  17. #include <mm\bitmask.h>
  18. #include <mm\reserve.h>
  19. #include <mm\range.h>
  20. #include <mm\subnet.h>
  21. #include <mm\sscope.h>
  22. #include <mm\oclassdl.h>
  23. #include <mm\server.h>
  24. #include <mm\address.h>
  25. #include <mm\server2.h>
  26. #include <mm\memfree.h>
  27. #include <mmreg\regutil.h>
  28. #include <mmreg\regread.h>
  29. #include <mmreg\regsave.h>
  30. #include <dhcpapi.h>
  31. #include <delete.h>
  32. #include <st_srvr.h>
  33. #include <upndown.h>
  34. #include <dnsapi.h>
  35. //================================================================================
  36. // helper functions
  37. //================================================================================
  38. #include <rpcapi2.h>
  39. //
  40. // Allow Debug prints to ntsd or kd
  41. //
  42. // #ifdef DBG
  43. // #define DsAuthPrint(_x_) DsAuthDebugPrintRoutine _x_
  44. // #else
  45. // #define DebugPrint(_x_)
  46. // #endif
  47. extern LPWSTR
  48. CloneString( IN LPWSTR String );
  49. typedef enum {
  50. LDAP_OPERATOR_EQUAL_TO,
  51. LDAP_OPERATOR_APPROX_EQUAL_TO,
  52. LDAP_OPERATOR_LESS_OR_EQUAL_TO,
  53. LDAP_OPERATOR_GREATER_OR_EQUAL_TO,
  54. LDAP_OPERATOR_AND,
  55. LDAP_OPERATOR_OR,
  56. LDAP_OPERATOR_NOT,
  57. LDAP_OPERATOR_TOTAL
  58. } LDAP_OPERATOR_ENUM;
  59. LPWSTR LdapOperators[ LDAP_OPERATOR_TOTAL ] =
  60. { L"=", L"~=", L"<=", L">=", L"&", L"|", L"!" };
  61. VOID DsAuthPrintRoutine(
  62. LPWSTR Format,
  63. ...
  64. )
  65. {
  66. WCHAR buf[2 * 256];
  67. va_list arg;
  68. DWORD len;
  69. va_start( arg, Format );
  70. len = wsprintf(buf, L"DSAUTH: ");
  71. wvsprintf( &buf[ len ], Format, arg );
  72. va_end( arg );
  73. OutputDebugString( buf );
  74. } // DsAuthPrint()
  75. //
  76. // This function creates an LDAP query filter string
  77. // with the option type, value and operator.
  78. //
  79. // Syntax:
  80. // primitive : <filter>=(<attribute><operator><value>)
  81. // complex : (<operator><filter1><filter2>)
  82. //
  83. LPWSTR
  84. MakeLdapFilter(
  85. IN LPWSTR Operand1,
  86. IN LDAP_OPERATOR_ENUM Operator,
  87. IN LPWSTR Operand2,
  88. IN BOOL Primitive
  89. )
  90. {
  91. LPWSTR Result;
  92. DWORD Size;
  93. DWORD Len;
  94. Result = NULL;
  95. AssertRet((( NULL != Operand1 ) &&
  96. ( NULL != Operand2 ) &&
  97. (( Operator >= 0 ) && ( Operator < LDAP_OPERATOR_TOTAL ))),
  98. NULL );
  99. // calculate the amount of memory needed
  100. Size = 0;
  101. Size += ROUND_UP_COUNT( sizeof( L"(" ), ALIGN_WORST );
  102. Size += ROUND_UP_COUNT( sizeof( L")" ), ALIGN_WORST );
  103. Size += ROUND_UP_COUNT( wcslen( Operand1 ), ALIGN_WORST );
  104. Size += ROUND_UP_COUNT( wcslen( Operand2 ), ALIGN_WORST );
  105. Size += ROUND_UP_COUNT( wcslen( LdapOperators[ Operator ] ), ALIGN_WORST );
  106. Size += 16; // padding
  107. Result = MemAlloc( Size * sizeof( WCHAR ));
  108. if ( NULL == Result ) {
  109. return NULL;
  110. }
  111. if ( Primitive ) {
  112. Len = wsprintf( Result,
  113. L"(%ws%ws%ws)",
  114. Operand1, LdapOperators[ Operator ], Operand2
  115. );
  116. }
  117. else {
  118. Len = wsprintf( Result,
  119. L"(%ws%ws%ws)",
  120. LdapOperators[ Operator ], Operand1, Operand2
  121. );
  122. } // else
  123. AssertRet( Len <= Size, NULL );
  124. return Result;
  125. } // MakeLdapFilter()
  126. //
  127. // Make a LDAP query filter like this:
  128. // (&(objectCategory=dHCPClass)(<operator>(dhcpServer="i<ip>$*")(dhcpServer="*s<hostname>*")))
  129. //
  130. LPWSTR
  131. MakeFilter(
  132. LPWSTR LookupServerIP, // Printable IP addr
  133. LPWSTR HostName,
  134. LDAP_OPERATOR_ENUM Operator
  135. )
  136. {
  137. LPWSTR Filter1, Filter2, Filter3, Filter4, SearchFilter;
  138. LPWSTR Buf;
  139. DWORD Len, CopiedLen;
  140. AssertRet((( NULL != LookupServerIP ) &&
  141. ( NULL != HostName )), NULL );
  142. Filter1 = NULL;
  143. Filter2 = NULL;
  144. Filter3 = NULL;
  145. Filter4 = NULL;
  146. SearchFilter = NULL;
  147. do {
  148. // Make large enough buffer
  149. Len = wcslen( HostName ) + wcslen( LookupServerIP ) + 10;
  150. Buf = MemAlloc( Len * sizeof( WCHAR ));
  151. if ( NULL == Buf ) {
  152. break;
  153. }
  154. // make (objectCategory=dHCPClass)
  155. Filter1 = MakeLdapFilter( ATTRIB_OBJECT_CATEGORY,
  156. LDAP_OPERATOR_EQUAL_TO,
  157. DEFAULT_DHCP_CLASS_ATTRIB_VALUE,
  158. TRUE );
  159. if ( NULL == Filter1 ) {
  160. break;
  161. }
  162. // The IP needs to be sent as i<ip>* to match the query
  163. // make (dhcpServers="i<ip>$*")
  164. CopiedLen = _snwprintf( Buf, Len - 1, L"i%ws$*", LookupServerIP );
  165. Require( CopiedLen > 0 );
  166. Filter2 = MakeLdapFilter( DHCP_ATTRIB_SERVERS,
  167. LDAP_OPERATOR_EQUAL_TO, Buf, TRUE );
  168. if ( NULL == Filter2 ) {
  169. break;
  170. }
  171. // make (dhcpServers="*s<hostname>$*")
  172. CopiedLen = _snwprintf( Buf, Len - 1, L"*s%ws$*", HostName );
  173. Require( CopiedLen > 0 );
  174. Filter3 = MakeLdapFilter( DHCP_ATTRIB_SERVERS,
  175. LDAP_OPERATOR_EQUAL_TO, Buf, TRUE );
  176. if ( NULL == Filter3 ) {
  177. break;
  178. }
  179. // make (<operator>(<ipfilter>)(<hostfilter))
  180. Filter4 = MakeLdapFilter( Filter2, Operator,
  181. Filter3, FALSE );
  182. if ( NULL == Filter4 ) {
  183. break;
  184. }
  185. // Finally make the filter to be returned
  186. SearchFilter = MakeLdapFilter( Filter1, LDAP_OPERATOR_AND,
  187. Filter4, FALSE );
  188. } while ( FALSE );
  189. if ( NULL != Buf ) {
  190. MemFree( Buf );
  191. }
  192. if ( NULL != Filter1 ) {
  193. MemFree( Filter1 );
  194. }
  195. if ( NULL != Filter2 ) {
  196. MemFree( Filter2 );
  197. }
  198. if ( NULL != Filter3 ) {
  199. MemFree( Filter3 );
  200. }
  201. if ( NULL != Filter4 ) {
  202. MemFree( Filter4 );
  203. }
  204. return SearchFilter;
  205. } // MakeFilter()
  206. //================================================================================
  207. // This function computes the unique identifier for a client; this is just
  208. // client subnet + client hw address type + client hw address. note that client
  209. // hardware address type is hardcoded as HARDWARE_TYPE_10MB_EITHERNET as there
  210. // is no way in the ui to specify type of reservations..
  211. // Also, DhcpValidateClient (cltapi.c?) uses the subnet address for validation.
  212. // Dont remove that.
  213. //================================================================================
  214. DWORD
  215. DhcpMakeClientUID( // compute unique identifier for the client
  216. IN LPBYTE ClientHardwareAddress,
  217. IN DWORD ClientHardwareAddressLength,
  218. IN BYTE ClientHardwareAddressType,
  219. IN DHCP_IP_ADDRESS ClientSubnetAddress,
  220. OUT LPBYTE *ClientUID, // will be allocated by function
  221. OUT DWORD *ClientUIDLength
  222. )
  223. {
  224. LPBYTE Buffer;
  225. LPBYTE ClientUIDBuffer;
  226. BYTE ClientUIDBufferLength;
  227. if( NULL == ClientUID || NULL == ClientUIDLength || 0 == ClientHardwareAddressLength )
  228. return ERROR_INVALID_PARAMETER;
  229. // see comment about on hardcoded hardware address type
  230. ClientHardwareAddressType = HARDWARE_TYPE_10MB_EITHERNET;
  231. ClientUIDBufferLength = sizeof(ClientSubnetAddress);
  232. ClientUIDBufferLength += sizeof(ClientHardwareAddressType);
  233. ClientUIDBufferLength += (BYTE)ClientHardwareAddressLength;
  234. ClientUIDBuffer = MemAlloc( ClientUIDBufferLength );
  235. if( ClientUIDBuffer == NULL ) {
  236. *ClientUIDLength = 0;
  237. return ERROR_NOT_ENOUGH_MEMORY;
  238. }
  239. Buffer = ClientUIDBuffer;
  240. RtlCopyMemory(Buffer,&ClientSubnetAddress,sizeof(ClientSubnetAddress));
  241. Buffer += sizeof(ClientSubnetAddress);
  242. RtlCopyMemory(Buffer,&ClientHardwareAddressType,sizeof(ClientHardwareAddressType) );
  243. Buffer += sizeof(ClientHardwareAddressType);
  244. RtlCopyMemory(Buffer,ClientHardwareAddress,ClientHardwareAddressLength );
  245. *ClientUID = ClientUIDBuffer;
  246. *ClientUIDLength = ClientUIDBufferLength;
  247. return ERROR_SUCCESS;
  248. }
  249. VOID static
  250. MemFreeFunc( // free memory
  251. IN OUT LPVOID Memory
  252. )
  253. {
  254. MemFree(Memory);
  255. }
  256. //DOC CreateServerObject creates the server object in the DS. It takes the
  257. //DOC ServerName parameter and names the object using this.
  258. //DOC The server is created with default values for most attribs.
  259. //DOC Several attribs are just not set.
  260. //DOC This returns ERROR_DDS_UNEXPECTED_ERROR if any DS operation fails.
  261. DWORD
  262. CreateServerObject( // create dhcp srvr obj in ds
  263. IN OUT LPSTORE_HANDLE hDhcpC, // container to creat obj in
  264. IN LPWSTR ServerName // [DNS?] name of server
  265. )
  266. {
  267. DWORD Err;
  268. LPWSTR ServerCNName; // container name
  269. ServerCNName = MakeColumnName(ServerName); // convert from "name" to "CN=name"
  270. if( NULL == ServerCNName ) return ERROR_NOT_ENOUGH_MEMORY;
  271. Err = StoreCreateObject // now create the object
  272. (
  273. /* hStore */ hDhcpC,
  274. /* Reserved */ DDS_RESERVED_DWORD,
  275. /* NewObjName */ ServerCNName,
  276. /* ... */
  277. /* Identification */
  278. ADSTYPE_DN_STRING, ATTRIB_DN_NAME, ServerName,
  279. ADSTYPE_DN_STRING, ATTRIB_OBJECT_CLASS, DEFAULT_DHCP_CLASS_ATTRIB_VALUE,
  280. /* systemMustContain */
  281. ADSTYPE_INTEGER, ATTRIB_DHCP_UNIQUE_KEY, 0,
  282. ADSTYPE_INTEGER, ATTRIB_DHCP_TYPE, DHCP_OBJ_TYPE_SERVER,
  283. ADSTYPE_DN_STRING, ATTRIB_DHCP_IDENTIFICATION, DHCP_OBJ_TYPE_SERVER_DESC,
  284. ADSTYPE_INTEGER, ATTRIB_DHCP_FLAGS, 0,
  285. ADSTYPE_INTEGER, ATTRIB_INSTANCE_TYPE, DEFAULT_INSTANCE_TYPE_ATTRIB_VALUE,
  286. /* terminator */
  287. ADSTYPE_INVALID
  288. );
  289. if( ERROR_ALREADY_EXISTS == Err ) { // if object exists, ignore this..
  290. Err = ERROR_SUCCESS;
  291. }
  292. MemFree(ServerCNName);
  293. return Err;
  294. }
  295. BOOL
  296. ServerMatched(
  297. IN PEATTRIB ThisAttrib,
  298. IN LPWSTR ServerName,
  299. IN ULONG IpAddress,
  300. OUT BOOL *fExactMatch
  301. )
  302. {
  303. BOOL fIpMatch, fNameMatch, fWildcardIp;
  304. (*fExactMatch) = FALSE;
  305. fIpMatch = (ThisAttrib->Address1 == IpAddress);
  306. if( INADDR_BROADCAST == ThisAttrib->Address1 ||
  307. INADDR_BROADCAST == IpAddress ) {
  308. fWildcardIp = TRUE;
  309. } else {
  310. fWildcardIp = FALSE;
  311. }
  312. if( FALSE == fIpMatch ) {
  313. //
  314. // If IP Addresses don't match, then check to see if
  315. // one of the IP addresses is a broadcast address..
  316. //
  317. if( !fWildcardIp ) return FALSE;
  318. }
  319. fNameMatch = DnsNameCompare_W(ThisAttrib->String1, ServerName);
  320. if( FALSE == fNameMatch ) {
  321. //
  322. // If names don't match _and_ IP's don't match, no match.
  323. //
  324. if( FALSE == fIpMatch || fWildcardIp ) return FALSE;
  325. } else {
  326. if( FALSE == fIpMatch ) return TRUE;
  327. (*fExactMatch) = TRUE;
  328. }
  329. return TRUE;
  330. }
  331. DWORD
  332. GetListOfAllServersMatchingFilter(
  333. IN OUT LPSTORE_HANDLE hDhcpC,
  334. IN OUT PARRAY Servers,
  335. IN LPWSTR SearchFilter OPTIONAL
  336. )
  337. {
  338. DWORD Err, LastErr;
  339. STORE_HANDLE hContainer;
  340. LPWSTR Filter;
  341. AssertRet( ( NULL != hDhcpC ) && ( NULL != Servers ),
  342. ERROR_INVALID_PARAMETER );
  343. Err = StoreSetSearchOneLevel(
  344. hDhcpC, DDS_RESERVED_DWORD );
  345. AssertRet( Err == NO_ERROR, Err );
  346. if ( NULL == SearchFilter ) {
  347. Filter = DHCP_SEARCH_FILTER;
  348. }
  349. else {
  350. Filter = SearchFilter;
  351. }
  352. AssertRet( NULL != Filter, ERROR_INVALID_PARAMETER );
  353. Err = StoreBeginSearch(
  354. hDhcpC, DDS_RESERVED_DWORD, Filter );
  355. AssertRet( Err == NO_ERROR, Err );
  356. while( TRUE ) {
  357. Err = StoreSearchGetNext(
  358. hDhcpC, DDS_RESERVED_DWORD, &hContainer );
  359. if( ERROR_DS_INVALID_DN_SYNTAX == Err ) {
  360. //
  361. // This nasty problem is because of an upgrade issue
  362. // in DS where some bad-named objects may exist..
  363. //
  364. Err = NO_ERROR;
  365. continue;
  366. }
  367. if( NO_ERROR != Err ) break;
  368. Err = DhcpDsGetLists
  369. (
  370. /* Reserved */ DDS_RESERVED_DWORD,
  371. /* hStore */ &hContainer,
  372. /* RecursionDepth */ 0xFFFFFFFF,
  373. /* Servers */ Servers, // array of PEATTRIB 's
  374. /* Subnets */ NULL,
  375. /* IpAddress */ NULL,
  376. /* Mask */ NULL,
  377. /* Ranges */ NULL,
  378. /* Sites */ NULL,
  379. /* Reservations */ NULL,
  380. /* SuperScopes */ NULL,
  381. /* OptionDescription */ NULL,
  382. /* OptionsLocation */ NULL,
  383. /* Options */ NULL,
  384. /* Classes */ NULL
  385. );
  386. StoreCleanupHandle( &hContainer, DDS_RESERVED_DWORD );
  387. if( NO_ERROR != Err ) break;
  388. }
  389. if( Err == ERROR_NO_MORE_ITEMS ) Err = NO_ERROR;
  390. LastErr = StoreEndSearch( hDhcpC, DDS_RESERVED_DWORD );
  391. //Require( LastErr == NO_ERROR );
  392. return Err;
  393. } // GetListOfAllServersMatchingFilter()
  394. DWORD
  395. DhcpDsAddServerInternal( // add a server in DS
  396. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  397. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  398. IN DWORD Reserved, // must be zero, future use
  399. IN LPWSTR ServerLocation,// Container where this will go in
  400. IN LPWSTR ServerName, // [DNS?] name of server
  401. IN LPWSTR ReservedPtr, // Server location? future use
  402. IN DWORD IpAddress, // ip address of server
  403. IN DWORD State // currently un-interpreted
  404. )
  405. {
  406. DWORD Err, Err2, unused;
  407. ARRAY Servers;
  408. ARRAY_LOCATION Loc;
  409. PEATTRIB ThisAttrib;
  410. EATTRIB DummyAttrib;
  411. if ( NULL == ServerLocation ) {
  412. return ERROR_INVALID_PARAMETER;
  413. }
  414. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  415. return ERROR_INVALID_PARAMETER;
  416. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  417. return ERROR_INVALID_PARAMETER;
  418. if( NULL == ServerName || 0 != Reserved )
  419. return ERROR_INVALID_PARAMETER;
  420. Err = MemArrayInit(&Servers); // cant fail
  421. //= require ERROR_SUCCESS == Err
  422. Err = DhcpDsGetLists // get list of servers for this object
  423. (
  424. /* Reserved */ DDS_RESERVED_DWORD,
  425. /* hStore */ hDhcpRoot,
  426. /* RecursionDepth */ 0xFFFFFFFF,
  427. /* Servers */ &Servers, // array of PEATTRIB 's
  428. /* Subnets */ NULL,
  429. /* IpAddress */ NULL,
  430. /* Mask */ NULL,
  431. /* Ranges */ NULL,
  432. /* Sites */ NULL,
  433. /* Reservations */ NULL,
  434. /* SuperScopes */ NULL,
  435. /* OptionDescription */ NULL,
  436. /* OptionsLocation */ NULL,
  437. /* Options */ NULL,
  438. /* Classes */ NULL
  439. );
  440. if( ERROR_SUCCESS != Err ) return Err;
  441. #ifdef DBG
  442. for( // search list of servers
  443. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  444. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  445. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  446. ) {
  447. BOOL fExactMatch = FALSE;
  448. //= require ERROR_SUCCESS == Err
  449. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  450. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  451. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  452. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  453. continue; //= ds inconsistent
  454. }
  455. if( ServerMatched(ThisAttrib, ServerName, IpAddress, &fExactMatch ) ) {
  456. //
  457. // Server found in the list of servers. Exact match not allowed.
  458. //
  459. Require( fExactMatch == FALSE );
  460. }
  461. } // for
  462. #endif
  463. NothingPresent(&DummyAttrib); // fill in attrib w/ srvr info
  464. STRING1_PRESENT(&DummyAttrib); // name
  465. ADDRESS1_PRESENT(&DummyAttrib); // ip addr
  466. FLAGS1_PRESENT(&DummyAttrib); // state
  467. DummyAttrib.String1 = ServerName;
  468. DummyAttrib.Address1 = IpAddress;
  469. DummyAttrib.Flags1 = State;
  470. if( ServerLocation ) {
  471. ADSPATH_PRESENT(&DummyAttrib); // ADsPath of location of server object
  472. STOREGETTYPE_PRESENT(&DummyAttrib);
  473. DummyAttrib.ADsPath = ServerLocation;
  474. DummyAttrib.StoreGetType = StoreGetChildType;
  475. }
  476. Err = MemArrayAddElement(&Servers, &DummyAttrib);
  477. if( ERROR_SUCCESS != Err ) { // could not add this to attrib array
  478. MemArrayFree(&Servers, MemFreeFunc); // free allocated memory
  479. return Err;
  480. }
  481. Err = DhcpDsSetLists // now set the new attrib list
  482. (
  483. /* Reserved */ DDS_RESERVED_DWORD,
  484. /* hStore */ hDhcpRoot,
  485. /* SetParams */ &unused,
  486. /* Servers */ &Servers,
  487. /* Subnets */ NULL,
  488. /* IpAddress */ NULL,
  489. /* Mask */ NULL,
  490. /* Ranges */ NULL,
  491. /* Sites */ NULL,
  492. /* Reservations */ NULL,
  493. /* SuperScopes */ NULL,
  494. /* OptionDescription.. */ NULL,
  495. /* OptionsLocation */ NULL,
  496. /* Options */ NULL,
  497. /* ClassDescription */ NULL,
  498. /* Classes */ NULL
  499. );
  500. Err2 = MemArrayLastLoc(&Servers, &Loc); // theres atleast 1 elt in array
  501. //= require ERROR_SUCCESS == Err2
  502. Err2 = MemArrayDelElement(&Servers, &Loc, &ThisAttrib);
  503. //= require ERROR_SUCCESS == Err2 && ThisAttrib == &DummyAttrib
  504. MemArrayFree(&Servers, MemFreeFunc); // free allocated memory
  505. return Err;
  506. } // DhcpDsAddServerInternal()
  507. //================================================================================
  508. // exported functions
  509. //================================================================================
  510. //BeginExport(function)
  511. //DOC DhcpDsAddServer adds a server's entry in the DS. Note that only the name
  512. //DOC uniquely determines the server. There can be one server with many ip addresses.
  513. //DOC If the server is created first time, a separate object is created for the
  514. //DOC server. : TO DO: The newly added server should also have its data
  515. //DOC updated in the DS uploaded from the server itself if it is still up.
  516. //DOC Note that it takes as parameter the Dhcp root container.
  517. //DOC If the requested address already exists in the DS (maybe to some other
  518. //DOC server), then the function returns ERROR_DDS_SERVER_ALREADY_EXISTS
  519. DWORD
  520. DhcpDsAddServer( // add a server in DS
  521. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  522. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  523. IN DWORD Reserved, // must be zero, future use
  524. IN LPWSTR ServerName, // [DNS?] name of server
  525. IN LPWSTR ReservedPtr, // Server location? future use
  526. IN DWORD IpAddress, // ip address of server
  527. IN DWORD State // currently un-interpreted
  528. ) //EndExport(function)
  529. {
  530. DWORD Err;
  531. ARRAY Servers;
  532. ARRAY_LOCATION Loc;
  533. LPWSTR ServerLocation;
  534. DWORD ServerLocType;
  535. STORE_HANDLE hDhcpServer;
  536. LPWSTR SearchFilter;
  537. WCHAR PrintableIp[ 20 ];
  538. LPWSTR SName;
  539. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  540. return ERROR_INVALID_PARAMETER;
  541. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  542. return ERROR_INVALID_PARAMETER;
  543. if( NULL == ServerName || 0 != Reserved )
  544. return ERROR_INVALID_PARAMETER;
  545. ServerLocation = NULL;
  546. do {
  547. Err = MemArrayInit( &Servers ); // cant fail
  548. //= require ERROR_SUCCESS == Err
  549. DsAuthPrint(( L"DhcpAddServer() \n" ));
  550. // Make a printable IP
  551. ConvertAddressToLPWSTR( IpAddress, PrintableIp );
  552. DsAuthPrint(( L"DhcpAddServer() : PrintableIp = %ws\n", PrintableIp ));
  553. SearchFilter = MakeFilter( PrintableIp, ServerName, LDAP_OPERATOR_AND );
  554. if ( NULL == SearchFilter ) {
  555. Err = ERROR_INVALID_PARAMETER; // get a better error code
  556. break;
  557. }
  558. DsAuthPrint(( L"DhcpDsAddServer() : Filter = %ws\n", SearchFilter ));
  559. Err = GetListOfAllServersMatchingFilter( hDhcpC, &Servers,
  560. SearchFilter );
  561. MemFree( SearchFilter );
  562. if( ERROR_SUCCESS != Err ) {
  563. break;
  564. }
  565. // There should only be one entry matching <hostname> and <ip>
  566. // if the entry already exists
  567. Require( MemArraySize( &Servers ) <= 1);
  568. if ( MemArraySize( &Servers ) > 0 ) {
  569. Err = ERROR_DDS_SERVER_ALREADY_EXISTS;
  570. break;
  571. }
  572. // Use the printable IP for the CN name
  573. Err = CreateServerObject(
  574. /* hDhcpC */ hDhcpC,
  575. /* ServerName */ PrintableIp
  576. );
  577. if( ERROR_SUCCESS != Err ) { // dont add server if obj cant be created
  578. break;
  579. }
  580. ServerLocation = MakeColumnName( PrintableIp );
  581. ServerLocType = StoreGetChildType;
  582. Err = StoreGetHandle( hDhcpC, 0, ServerLocType, ServerLocation, &hDhcpServer );
  583. if( NO_ERROR == Err ) {
  584. Err = DhcpDsAddServerInternal( hDhcpC, &hDhcpServer, Reserved, ServerLocation,
  585. ServerName, ReservedPtr,
  586. IpAddress, State );
  587. StoreCleanupHandle( &hDhcpServer, 0 );
  588. }
  589. } while ( FALSE );
  590. // clean up the allocated memory
  591. MemArrayFree(&Servers, MemFreeFunc);
  592. MemArrayCleanup( &Servers );
  593. if( NULL != ServerLocation ) {
  594. MemFree( ServerLocation );
  595. }
  596. DsAuthPrint(( L"DhcpDsAddServer() done\n" ));
  597. return Err;
  598. } // DhcpDsAddServer()
  599. DWORD
  600. DhcpDsDelServerInternal( // Delete a server from memory
  601. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  602. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  603. IN DWORD Reserved, // must be zero, for future use
  604. IN LPWSTR ServerLocation,// Container where this will go in
  605. IN LPWSTR ServerName, // which server to delete for
  606. IN LPWSTR ReservedPtr, // server location ? future use
  607. IN DWORD IpAddress // the IpAddress to delete..
  608. )
  609. {
  610. DWORD Err, Err2, unused;
  611. ARRAY Servers;
  612. ARRAY_LOCATION Loc;
  613. PEATTRIB ThisAttrib;
  614. BOOL fServerExists;
  615. BOOL fServerDeleted;
  616. if ( NULL == ServerLocation ) {
  617. return ERROR_INVALID_PARAMETER;
  618. }
  619. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  620. return ERROR_INVALID_PARAMETER;
  621. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  622. return ERROR_INVALID_PARAMETER;
  623. if( NULL == ServerName || 0 != Reserved )
  624. return ERROR_INVALID_PARAMETER;
  625. Err = MemArrayInit(&Servers); // cant fail
  626. //= require ERROR_SUCCESS == Err
  627. Err = DhcpDsGetLists // get list of servers for this object
  628. (
  629. /* Reserved */ DDS_RESERVED_DWORD,
  630. /* hStore */ hDhcpRoot,
  631. /* RecursionDepth */ 0xFFFFFFFF,
  632. /* Servers */ &Servers, // array of PEATTRIB 's
  633. /* Subnets */ NULL,
  634. /* IpAddress */ NULL,
  635. /* Mask */ NULL,
  636. /* Ranges */ NULL,
  637. /* Sites */ NULL,
  638. /* Reservations */ NULL,
  639. /* SuperScopes */ NULL,
  640. /* OptionDescription */ NULL,
  641. /* OptionsLocation */ NULL,
  642. /* Options */ NULL,
  643. /* Classes */ NULL
  644. );
  645. if( ERROR_SUCCESS != Err ) return Err;
  646. fServerDeleted = FALSE;
  647. for( // search list of servers
  648. Err = MemArrayInitLoc( &Servers, &Loc ) // initialize
  649. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  650. Err = MemArrayNextLoc( &Servers, &Loc ) // skip to next element
  651. ) {
  652. BOOL fExactMatch = FALSE;
  653. //= require ERROR_SUCCESS == Err
  654. Err = MemArrayGetElement( &Servers, &Loc, &ThisAttrib );
  655. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  656. if( !IS_STRING1_PRESENT( ThisAttrib) || // no name for this server
  657. !IS_ADDRESS1_PRESENT( ThisAttrib) ) { // no address for this server
  658. continue; //= ds inconsistent
  659. }
  660. if( ServerMatched( ThisAttrib, ServerName, IpAddress, &fExactMatch )) {
  661. //
  662. // Server found. If exact match, remove the element from list.
  663. //
  664. if( fExactMatch ) {
  665. Err2 = MemArrayDelElement( &Servers, &Loc, &ThisAttrib );
  666. fServerDeleted = TRUE;
  667. break;
  668. }
  669. } // if
  670. } // for
  671. Require( fServerDeleted == TRUE );
  672. if ( MemArraySize( &Servers ) > 0 ) {
  673. // now set the new attrib list
  674. Err = DhcpDsSetLists( DDS_RESERVED_DWORD, hDhcpRoot, &unused, &Servers,
  675. NULL, NULL, NULL, NULL, NULL, NULL,
  676. NULL, NULL, NULL, NULL, NULL, NULL );
  677. MemArrayFree(&Servers, MemFreeFunc);
  678. } // if
  679. else {
  680. // this empty object needs to be deleted from the DS
  681. Err = StoreDeleteThisObject( hDhcpC, DDS_RESERVED_DWORD,
  682. StoreGetChildType,
  683. ServerLocation );
  684. } // else
  685. return Err;
  686. } // DhcpDsDelServerInternal()
  687. //BeginExport(function)
  688. //DOC DhcpDsDelServer removes the requested servername-ipaddress pair from the ds.
  689. //DOC If this is the last ip address for the given servername, then the server
  690. //DOC is also removed from memory. But objects referred by the Server are left in
  691. //DOC the DS as they may also be referred to from else where. This needs to be
  692. //DOC fixed via references being tagged as direct and symbolic -- one causing deletion
  693. //DOC and other not causing any deletion. THIS NEEDS TO BE FIXED.
  694. DWORD
  695. DhcpDsDelServer( // Delete a server from memory
  696. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  697. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  698. IN DWORD Reserved, // must be zero, for future use
  699. IN LPWSTR ServerName, // which server to delete for
  700. IN LPWSTR ReservedPtr, // server location ? future use
  701. IN DWORD IpAddress // the IpAddress to delete..
  702. ) //EndExport(function)
  703. {
  704. DWORD Err, Loc;
  705. ARRAY Servers;
  706. PEATTRIB ThisAttrib;
  707. WCHAR PrintableIp[ 20 ];
  708. LPWSTR SearchFilter;
  709. STORE_HANDLE hObj;
  710. do {
  711. Err = MemArrayInit( &Servers );
  712. DsAuthPrint(( L"DhcpDelServer() \n" ));
  713. ConvertAddressToLPWSTR( IpAddress, PrintableIp );
  714. SearchFilter = MakeFilter( PrintableIp, ServerName, LDAP_OPERATOR_AND );
  715. if ( NULL == SearchFilter ) {
  716. Err = ERROR_INVALID_PARAMETER; // get a better error code
  717. break;
  718. }
  719. DsAuthPrint(( L"DhcpDsDelServer() : Filter = %ws\n", SearchFilter ));
  720. Err = GetListOfAllServersMatchingFilter( hDhcpC, &Servers,
  721. SearchFilter );
  722. MemFree( SearchFilter );
  723. // GetListOfAllServersMatchingFilter() returns the dhcp servers
  724. // defined the in all the maching objects, so it also returns false
  725. // objects.
  726. // Since we are using '&' operator for ip and host name, it will return
  727. // a single object. However, that object may contain more than one entries
  728. // in dhcpServers attribute.
  729. if ( MemArraySize( &Servers ) == 0 ) {
  730. Err = ERROR_DDS_SERVER_DOES_NOT_EXIST;
  731. break;
  732. }
  733. // get the object CN. This is okay since it returns only one object.
  734. Err = MemArrayInitLoc( &Servers, &Loc );
  735. Err = MemArrayGetElement( &Servers, &Loc, &ThisAttrib );
  736. Require( NULL != ThisAttrib );
  737. Require( NULL != ThisAttrib->ADsPath );
  738. // get a handle to the object that contains the server to be deleted
  739. Err = StoreGetHandle( hDhcpC, DDS_RESERVED_DWORD,
  740. StoreGetChildType, ThisAttrib->ADsPath,
  741. &hObj );
  742. if ( ERROR_SUCCESS != Err ) {
  743. break;
  744. }
  745. // ADsPath is cn=xxxx, get rid of 'cn='
  746. Err = DhcpDsDelServerInternal( hDhcpC, &hObj, Reserved,
  747. ThisAttrib->ADsPath, ServerName,
  748. ReservedPtr, IpAddress );
  749. // Ignore the error
  750. (void ) StoreCleanupHandle( &hObj, 0 );
  751. } while ( FALSE );
  752. // Free allocated memory
  753. MemArrayFree( &Servers, MemFreeFunc );
  754. DsAuthPrint(( L"DhcpDsDelServer() exiting...\n" ));
  755. return Err;
  756. } // DhcpDsDelServer()
  757. //BeginExport(function)
  758. BOOL
  759. DhcpDsLookupServer( // get info about a server
  760. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  761. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  762. IN DWORD Reserved, // must be zero, for future use
  763. IN LPWSTR LookupServerIP,// Server to lookup IP
  764. IN LPWSTR HostName // Hostname to lookup
  765. ) //EndExport(function)
  766. {
  767. DWORD Err, Err2, Size, Size2, i, N;
  768. ARRAY Servers;
  769. ARRAY_LOCATION Loc;
  770. PEATTRIB ThisAttrib;
  771. LPDHCPDS_SERVERS LocalServers;
  772. LPBYTE Ptr;
  773. LPWSTR SearchFilter;
  774. STORE_HANDLE hContainer;
  775. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  776. return FALSE;
  777. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  778. return FALSE;
  779. if (( NULL == HostName ) ||
  780. ( NULL == LookupServerIP )) {
  781. return FALSE;
  782. }
  783. SearchFilter = MakeFilter( LookupServerIP, HostName, LDAP_OPERATOR_OR );
  784. if ( NULL == SearchFilter ) {
  785. return FALSE;
  786. }
  787. DsAuthPrint(( L"hostname = %ws, IP = %ws, Filter = %ws\n",
  788. HostName, LookupServerIP, SearchFilter ));
  789. Err = StoreSetSearchOneLevel( hDhcpC, DDS_RESERVED_DWORD );
  790. AssertRet( Err == NO_ERROR, Err );
  791. Err = StoreBeginSearch( hDhcpC, DDS_RESERVED_DWORD, SearchFilter );
  792. MemFree( SearchFilter );
  793. AssertRet( Err == NO_ERROR, Err );
  794. Err = StoreSearchGetNext( hDhcpC, DDS_RESERVED_DWORD, &hContainer );
  795. StoreEndSearch( hDhcpC, DDS_RESERVED_DWORD );
  796. return ( NO_ERROR == Err );
  797. } // DhcpDsLookupServer()
  798. //BeginExport(function)
  799. //DOC DhcpDsEnumServers retrieves a bunch of information about each server that
  800. //DOC has an entry in the Servers attribute of the root object. There are no guarantees
  801. //DOC on the order..
  802. //DOC The memory for this is allocated in ONE shot -- so the output can be freed in
  803. //DOC one shot too.
  804. //DOC
  805. DWORD
  806. DhcpDsEnumServers( // get info abt all existing servers
  807. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  808. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  809. IN DWORD Reserved, // must be zero, for future use
  810. OUT LPDHCPDS_SERVERS *ServersInfo // array of servers
  811. ) //EndExport(function)
  812. {
  813. DWORD Err, Err2, Size, Size2, i, N;
  814. ARRAY Servers;
  815. ARRAY_LOCATION Loc;
  816. PEATTRIB ThisAttrib;
  817. LPDHCPDS_SERVERS LocalServers;
  818. LPBYTE Ptr;
  819. LPWSTR Filter1, Filter2, Filter3;
  820. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  821. return ERROR_INVALID_PARAMETER;
  822. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  823. return ERROR_INVALID_PARAMETER;
  824. if( 0 != Reserved || NULL == ServersInfo )
  825. return ERROR_INVALID_PARAMETER;
  826. *ServersInfo = NULL; i = N = Size = Size2 = 0;
  827. Err = MemArrayInit(&Servers); // cant fail
  828. //= require ERROR_SUCCESS == Err
  829. DsAuthPrint(( L"DhcpDsEnumServers \n" ));
  830. Err = GetListOfAllServersMatchingFilter( hDhcpC, &Servers,
  831. DHCP_SEARCH_FILTER );
  832. if( ERROR_SUCCESS != Err ) return Err;
  833. Size = Size2 = 0;
  834. for( // walk thru list of servers
  835. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  836. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  837. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  838. ) {
  839. //= require ERROR_SUCCESS == Err
  840. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  841. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  842. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  843. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  844. continue; //= ds inconsistent
  845. }
  846. Size2 = sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1));
  847. if( IS_ADSPATH_PRESENT(ThisAttrib) ) { // if ADsPath there, account for it
  848. Size2 += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->ADsPath));
  849. }
  850. Size += Size2; // keep track of total mem reqd
  851. i ++;
  852. }
  853. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVERS), ALIGN_WORST);
  854. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVER)*i, ALIGN_WORST);
  855. Ptr = MIDL_user_allocate(Size); // allocate memory
  856. if( NULL == Ptr ) {
  857. MemArrayFree(&Servers, MemFreeFunc ); // free allocated memory
  858. return ERROR_NOT_ENOUGH_MEMORY;
  859. }
  860. LocalServers = (LPDHCPDS_SERVERS)Ptr;
  861. LocalServers->NumElements = i;
  862. LocalServers->Flags = 0;
  863. Size = 0; // start from offset 0
  864. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVERS), ALIGN_WORST);
  865. LocalServers->Servers = (LPDHCPDS_SERVER)(Size + Ptr);
  866. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVER)*i, ALIGN_WORST);
  867. i = Size2 = 0;
  868. for( // copy list of servers
  869. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  870. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  871. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  872. ) {
  873. //= require ERROR_SUCCESS == Err
  874. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  875. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  876. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  877. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  878. continue; //= ds inconsistent
  879. }
  880. LocalServers->Servers[i].Version =0; // version is always zero in this build
  881. LocalServers->Servers[i].State=0;
  882. LocalServers->Servers[i].ServerName = (LPWSTR)(Size + Ptr);
  883. wcscpy((LPWSTR)(Size+Ptr), ThisAttrib->String1);
  884. Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1));
  885. LocalServers->Servers[i].ServerAddress = ThisAttrib->Address1;
  886. if( IS_FLAGS1_PRESENT(ThisAttrib) ) { // State present
  887. LocalServers->Servers[i].Flags = ThisAttrib->Flags1;
  888. } else {
  889. LocalServers->Servers[i].Flags = 0; // if no flags present, use zero
  890. }
  891. if( IS_ADSPATH_PRESENT(ThisAttrib) ) { // if ADsPath there, copy it too
  892. LocalServers->Servers[i].DsLocType = ThisAttrib->StoreGetType;
  893. LocalServers->Servers[i].DsLocation = (LPWSTR)(Size + Ptr);
  894. wcscpy((LPWSTR)(Size + Ptr), ThisAttrib->ADsPath);
  895. Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->ADsPath));
  896. } else { // no ADsPath present
  897. LocalServers->Servers[i].DsLocType = 0;
  898. LocalServers->Servers[i].DsLocation = NULL;
  899. }
  900. i ++;
  901. }
  902. *ServersInfo = LocalServers;
  903. MemArrayFree(&Servers, MemFreeFunc ); // free allocated memory
  904. return ERROR_SUCCESS;
  905. } // DhcpDsEnumServers()
  906. //================================================================================
  907. // end of file
  908. //================================================================================