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.

776 lines
28 KiB

  1. //--------------------------------------------------------------------------------
  2. // Copyright (C) Micorosoft Confidential 1997
  3. // Author: RameshV
  4. // Description: Option related registry handling -- common between NT and VxD
  5. //--------------------------------------------------------------------------------
  6. #include <wininetp.h>
  7. #include "aproxp.h"
  8. #ifndef OPTREG_H
  9. #define OPTREG_H
  10. //--------------------------------------------------------------------------------
  11. // function definitions
  12. //--------------------------------------------------------------------------------
  13. POPTION // option from which more appends can occur
  14. DhcpAppendSendOptions( // append all configured options
  15. IN OUT PDHCP_CONTEXT DhcpContext, // this is the context to append for
  16. IN PLIST_ENTRY SendOptionsList,
  17. IN LPBYTE ClassName, // current class
  18. IN DWORD ClassLen, // len of above in bytes
  19. IN LPBYTE BufStart, // start of buffer
  20. IN LPBYTE BufEnd, // how far can we go in this buffer
  21. IN OUT LPBYTE SentOptions, // BoolArray[OPTION_END+1] to avoid repeating options
  22. IN OUT LPBYTE VSentOptions, // to avoid repeating vendor specific options
  23. IN OUT LPBYTE VendorOpt, // Buffer[OPTION_END+1] Holding Vendor specific options
  24. OUT LPDWORD VendorOptLen // the # of bytes filled into that
  25. );
  26. DWORD // status
  27. DhcpDestroyOptionsList( // destroy a list of options, freeing up memory
  28. IN OUT PLIST_ENTRY OptionsList, // this is the list of options to destroy
  29. IN PLIST_ENTRY ClassesList // this is where to remove classes off
  30. );
  31. DWORD // win32 status
  32. DhcpClearAllOptions( // remove all turds from off registry
  33. IN OUT PDHCP_CONTEXT DhcpContext // the context to clear for
  34. );
  35. #endif OPTREG_H
  36. // internal private function that takes the lock on OPTIONS_LIST
  37. DWORD // status
  38. DhcpRegClearOptDefs( // clear all standard options
  39. IN LPTSTR AdapterName // clear for this adapter
  40. );
  41. //
  42. // options related lists
  43. //
  44. LIST_ENTRY DhcpGlobalRecvFromList;
  45. LPSTR DhcpGlobalClientClassInfo = NULL;
  46. LPBYTE // ptr to buf loc where more appends can occur
  47. DhcpAppendParamRequestList( // append the param request list option
  48. IN PDHCP_CONTEXT DhcpContext, // the context to append for
  49. IN PLIST_ENTRY SendOptionsList,// look thru this list
  50. IN LPBYTE ClassName, // which class does this belong to?
  51. IN DWORD ClassLen, // size of above in bytes
  52. IN LPBYTE BufStart, // where to start adding this option
  53. IN LPBYTE BufEnd // limit for this option
  54. ) {
  55. BYTE Buffer[OPTION_END+1];
  56. LPBYTE Tmp;
  57. DWORD FirstSize;
  58. DWORD Size;
  59. PLIST_ENTRY ThisEntry;
  60. PDHCP_OPTION ThisOpt;
  61. DWORD i, j;
  62. Size = FirstSize = 0;
  63. Buffer[Size++] = OPTION_SUBNET_MASK; // standard requested options
  64. Buffer[Size++] = OPTION_DOMAIN_NAME;
  65. Buffer[Size++] = OPTION_ROUTER_ADDRESS;
  66. Buffer[Size++] = OPTION_DOMAIN_NAME_SERVERS;
  67. Buffer[Size++] = OPTION_NETBIOS_NAME_SERVER;
  68. Buffer[Size++] = OPTION_NETBIOS_NODE_TYPE;
  69. Buffer[Size++] = OPTION_NETBIOS_SCOPE_OPTION;
  70. Buffer[Size++] = OPTION_VENDOR_SPEC_INFO;
  71. Buffer[Size++] = OPTION_USER_CLASS;
  72. Buffer[Size++] = OPTION_WPAD_URL;
  73. ThisEntry = SendOptionsList->Flink;
  74. while( ThisEntry != SendOptionsList ) {
  75. ThisOpt = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
  76. ThisEntry = ThisEntry->Flink;
  77. if( ThisOpt->IsVendor) continue;
  78. if( ThisOpt->ClassLen ) {
  79. if( ThisOpt->ClassLen != ClassLen ) continue;
  80. if( ThisOpt->ClassName != ClassName )
  81. continue; // this option is not used for this client
  82. }
  83. if( OPTION_PARAMETER_REQUEST_LIST != ThisOpt->OptionId ) {
  84. //
  85. // only if the option is param_request_list do we request..
  86. //
  87. continue;
  88. }
  89. for( i = 0; i < ThisOpt->DataLen ; i ++ ) {
  90. for( j = 0; j < Size; j ++ )
  91. if( ThisOpt->Data[i] == Buffer[j] ) break;
  92. if( j < Size ) continue; // option already plugged in
  93. Buffer[Size++] = ThisOpt->Data[i]; // add this option
  94. }
  95. if( 0 == FirstSize ) FirstSize = Size;
  96. }
  97. if( 0 == FirstSize ) FirstSize = Size;
  98. Tmp = BufStart;
  99. BufStart = (LPBYTE)DhcpAppendOption( // now add the param request list
  100. (POPTION)BufStart,
  101. (BYTE)OPTION_PARAMETER_REQUEST_LIST,
  102. Buffer,
  103. (BYTE)Size,
  104. BufEnd
  105. );
  106. if( Tmp == BufStart ) { // did not really add the option
  107. BufStart = (LPBYTE)DhcpAppendOption( // now try adding the first request we saw instead of everything
  108. (POPTION)BufStart,
  109. (BYTE)OPTION_PARAMETER_REQUEST_LIST,
  110. Buffer,
  111. (BYTE)FirstSize,
  112. BufEnd
  113. );
  114. }
  115. return BufStart;
  116. }
  117. POPTION // option from which more appends can occur
  118. DhcpAppendSendOptions( // append all configured options
  119. IN OUT PDHCP_CONTEXT DhcpContext, // this is the context to append for
  120. IN PLIST_ENTRY SendOptionsList,
  121. IN LPBYTE ClassName, // current class
  122. IN DWORD ClassLen, // len of above in bytes
  123. IN LPBYTE BufStart, // start of buffer
  124. IN LPBYTE BufEnd, // how far can we go in this buffer
  125. IN OUT LPBYTE SentOptions, // BoolArray[OPTION_END+1] to avoid repeating options
  126. IN OUT LPBYTE VSentOptions, // to avoid repeating vendor specific options
  127. IN OUT LPBYTE VendorOpt, // Buffer[OPTION_END+1] Holding Vendor specific options
  128. OUT LPDWORD VendorOptLen // the # of bytes filled into that
  129. ) {
  130. PLIST_ENTRY ThisEntry;
  131. PDHCP_OPTION ThisOpt;
  132. DhcpAssert(FALSE == SentOptions[OPTION_PARAMETER_REQUEST_LIST]);
  133. BufStart = DhcpAppendParamRequestList(
  134. DhcpContext,
  135. SendOptionsList,
  136. ClassName,
  137. ClassLen,
  138. BufStart,
  139. BufEnd
  140. );
  141. SentOptions[OPTION_PARAMETER_REQUEST_LIST] = TRUE;
  142. ThisEntry = SendOptionsList->Flink;
  143. while( ThisEntry != SendOptionsList ) {
  144. ThisOpt = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
  145. ThisEntry = ThisEntry->Flink;
  146. if( ThisOpt->IsVendor ? VSentOptions[ThisOpt->OptionId] : SentOptions[ThisOpt->OptionId] )
  147. continue;
  148. // if( ThisOpt->IsVendor) continue; // No vendor specific information this round through
  149. if( ThisOpt->ClassLen ) {
  150. if( ThisOpt->ClassLen != ClassLen ) continue;
  151. if( ThisOpt->ClassName != ClassName )
  152. continue; // this option is not used for this client
  153. }
  154. if( !ThisOpt->IsVendor ) { // easy to add non-vendor spec options
  155. SentOptions[ThisOpt->OptionId] = TRUE;
  156. BufStart = (LPBYTE)DhcpAppendOption(
  157. (POPTION)BufStart,
  158. ThisOpt->OptionId,
  159. ThisOpt->Data,
  160. (BYTE)ThisOpt->DataLen,
  161. BufEnd
  162. );
  163. } else { // ENCAPSULATE vendor specific options
  164. if( SentOptions[OPTION_VENDOR_SPEC_INFO] )
  165. continue; // Vendor spec info already added
  166. VSentOptions[ThisOpt->OptionId] = TRUE;
  167. if( ThisOpt->DataLen + 2 + *VendorOptLen > OPTION_END )
  168. continue; // this option overflows the buffer
  169. VendorOpt[(*VendorOptLen)++] = ThisOpt->OptionId;
  170. VendorOpt[(*VendorOptLen)++] = (BYTE)ThisOpt->DataLen;
  171. memcpy(&VendorOpt[*VendorOptLen], ThisOpt->Data, ThisOpt->DataLen);
  172. (*VendorOptLen) += ThisOpt->DataLen;
  173. }
  174. }
  175. return (POPTION)BufStart;
  176. }
  177. DWORD // status
  178. DhcpDestroyOptionsList( // destroy a list of options, freeing up memory
  179. IN OUT PLIST_ENTRY OptionsList, // this is the list of options to destroy
  180. IN PLIST_ENTRY ClassesList // this is where to remove classes off
  181. ) {
  182. PLIST_ENTRY ThisEntry;
  183. PDHCP_OPTION ThisOption;
  184. DWORD Error;
  185. DWORD LastError;
  186. LastError = ERROR_SUCCESS;
  187. while(!IsListEmpty(OptionsList) ) { // for each element of this list
  188. ThisEntry = RemoveHeadList(OptionsList);
  189. ThisOption = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
  190. if( NULL != ThisOption->ClassName ) { // if there is a class, deref it
  191. Error = DhcpDelClass(
  192. ClassesList,
  193. ThisOption->ClassName,
  194. ThisOption->ClassLen
  195. );
  196. if( ERROR_SUCCESS != Error ) {
  197. DhcpAssert( ERROR_SUCCESS == Error);
  198. LastError = Error;
  199. }
  200. }
  201. DhcpFreeMemory(ThisOption); // now really free this
  202. }
  203. return LastError;
  204. }
  205. DWORD // win32 status
  206. DhcpClearAllOptions( // clear all the options information
  207. IN OUT PDHCP_CONTEXT DhcpContext // the context to clear for
  208. ) {
  209. PLIST_ENTRY ThisEntry;
  210. PDHCP_OPTION ThisOption;
  211. DWORD LocalError;
  212. //(void) DhcpRegClearOptDefs(DhcpContext->AdapterName));
  213. ThisEntry = DhcpContext->RecdOptionsList.Flink;
  214. while(ThisEntry != &DhcpContext->RecdOptionsList) {
  215. ThisOption = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
  216. ThisEntry = ThisEntry->Flink;
  217. // bug bug, need to return space?
  218. ThisOption->Data = NULL;
  219. ThisOption->DataLen = 0;
  220. //LocalError = DhcpMarkParamChangeRequests(
  221. // DhcpContext->AdapterName,
  222. // ThisOption->OptionId,
  223. // ThisOption->IsVendor,
  224. // ThisOption->ClassName
  225. //);
  226. DhcpAssert(ERROR_SUCCESS == LocalError);
  227. }
  228. return ERROR_SUCCESS;
  229. }
  230. POPTION // buffer after filling option
  231. DhcpAppendClassIdOption( // fill class id if exists
  232. IN OUT PDHCP_CONTEXT DhcpContext, // the context to fillfor
  233. OUT LPBYTE BufStart, // start of message buffer
  234. IN LPBYTE BufEnd // end of message buffer
  235. ) {
  236. DWORD Size;
  237. Size = (DWORD)(BufEnd - BufStart);
  238. if( DhcpContext->ClassId ) {
  239. DhcpAssert(DhcpContext->ClassIdLength);
  240. BufStart = (LPBYTE)DhcpAppendOption(
  241. (POPTION)BufStart,
  242. OPTION_USER_CLASS,
  243. DhcpContext->ClassId,
  244. (BYTE)DhcpContext->ClassIdLength,
  245. BufEnd
  246. );
  247. }
  248. return (POPTION) BufStart;
  249. }
  250. LPOPTION
  251. DhcpAppendOption(
  252. LPOPTION Option,
  253. BYTE OptionType,
  254. PVOID OptionValue,
  255. ULONG OptionLength,
  256. LPBYTE OptionEnd
  257. )
  258. /*++
  259. Routine Description:
  260. This function writes a DHCP option to message buffer.
  261. Arguments:
  262. Option - A pointer to a message buffer.
  263. OptionType - The option number to append.
  264. OptionValue - A pointer to the option data.
  265. OptionLength - The lenght, in bytes, of the option data.
  266. OptionEnd - End of Option Buffer.
  267. Return Value:
  268. A pointer to the end of the appended option.
  269. --*/
  270. {
  271. DWORD i;
  272. if ( OptionType == OPTION_END ) {
  273. //
  274. // we should alway have atleast one BYTE space in the buffer
  275. // to append this option.
  276. //
  277. DhcpAssert( (LPBYTE)Option < OptionEnd );
  278. Option->OptionType = OPTION_END;
  279. return( (LPOPTION) ((LPBYTE)(Option) + 1) );
  280. }
  281. if ( OptionType == OPTION_PAD ) {
  282. //
  283. // add this option only iff we have enough space in the buffer.
  284. //
  285. if(((LPBYTE)Option + 1) < (OptionEnd - 1) ) {
  286. Option->OptionType = OPTION_PAD;
  287. return( (LPOPTION) ((LPBYTE)(Option) + 1) );
  288. }
  289. DhcpPrint(("DhcpAppendOption failed to append Option "
  290. "%ld, Buffer too small.\n", OptionType ));
  291. return Option;
  292. }
  293. //
  294. // add this option only iff we have enough space in the buffer.
  295. //
  296. if(((LPBYTE)Option + 2 + OptionLength) >= (OptionEnd - 1) ) {
  297. DhcpPrint(("DhcpAppendOption failed to append Option "
  298. "%ld, Buffer too small.\n", OptionType ));
  299. return Option;
  300. }
  301. if( OptionLength <= 0xFF ) {
  302. // simple option.. no need to use OPTION_MSFT_CONTINUED
  303. Option->OptionType = OptionType;
  304. Option->OptionLength = (BYTE)OptionLength;
  305. memcpy( Option->OptionValue, OptionValue, OptionLength );
  306. return( (LPOPTION) ((LPBYTE)(Option) + Option->OptionLength + 2) );
  307. }
  308. // option size is > 0xFF --> need to continue it using multiple ones..
  309. // there are OptionLenght / 0xFF occurances using 0xFF+2 bytes + one
  310. // using 2 + (OptionLength % 0xFF ) space..
  311. // check to see if we have the space first..
  312. if( 2 + (OptionLength%0xFF) + 0x101*(OptionLength/0xFF)
  313. + (LPBYTE)Option >= (OptionEnd - 1) ) {
  314. DhcpPrint(("DhcpAppendOption failed to append Option "
  315. "%ld, Buffer too small.\n", OptionType ));
  316. return Option;
  317. }
  318. // first finish off all chunks of 0xFF size that we can do..
  319. i = OptionLength/0xFF;
  320. while(i) {
  321. Option->OptionType = OptionType;
  322. Option->OptionLength = 0xFF;
  323. memcpy(Option->OptionValue, OptionValue, 0xFF);
  324. OptionValue = 0xFF+(LPBYTE)OptionValue;
  325. Option = (LPOPTION)(0x101 + (LPBYTE)Option);
  326. OptionType = OPTION_MSFT_CONTINUED; // all but the first use this ...
  327. OptionLength -= 0xFF;
  328. }
  329. // now finish off the remaining stuff..
  330. DhcpAssert(OptionLength <= 0xFF);
  331. Option->OptionType = OPTION_MSFT_CONTINUED;
  332. Option->OptionLength = (BYTE)OptionLength;
  333. memcpy(Option->OptionValue, OptionValue, OptionLength);
  334. Option = (LPOPTION)(2 + OptionLength + (LPBYTE)Option);
  335. DhcpAssert((LPBYTE)Option < OptionEnd);
  336. return Option;
  337. }
  338. LPBYTE
  339. DhcpAppendMagicCookie(
  340. LPBYTE Option,
  341. LPBYTE OptionEnd
  342. )
  343. /*++
  344. Routine Description:
  345. This routine appends magic cookie to a DHCP message.
  346. Arguments:
  347. Option - A pointer to the place to append the magic cookie.
  348. OptionEnd - End of Option buffer.
  349. Return Value:
  350. A pointer to the end of the appended cookie.
  351. Note : The magic cookie is :
  352. --------------------
  353. | 99 | 130 | 83 | 99 |
  354. --------------------
  355. --*/
  356. {
  357. DhcpAssert( (Option + 4) < (OptionEnd - 1) );
  358. if( (Option + 4) < (OptionEnd - 1) ) {
  359. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE1;
  360. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE2;
  361. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE3;
  362. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE4;
  363. }
  364. return( Option );
  365. }
  366. LPOPTION
  367. DhcpAppendClientIDOption(
  368. LPOPTION Option,
  369. BYTE ClientHWType,
  370. LPBYTE ClientHWAddr,
  371. BYTE ClientHWAddrLength,
  372. LPBYTE OptionEnd
  373. )
  374. /*++
  375. Routine Description:
  376. This routine appends client ID option to a DHCP message.
  377. History:
  378. 8/26/96 Frankbee Removed 16 byte limitation on the hardware
  379. address
  380. Arguments:
  381. Option - A pointer to the place to append the option request.
  382. ClientHWType - Client hardware type.
  383. ClientHWAddr - Client hardware address
  384. ClientHWAddrLength - Client hardware address length.
  385. OptionEnd - End of Option buffer.
  386. Return Value:
  387. A pointer to the end of the newly appended option.
  388. Note : The client ID option will look like as below in the message:
  389. -----------------------------------------------------------------
  390. | OpNum | Len | HWType | HWA1 | HWA2 | ..... | HWAn |
  391. -----------------------------------------------------------------
  392. --*/
  393. {
  394. #pragma warning(disable : 4200) // disable 0-sized array warning
  395. struct _CLIENT_ID {
  396. BYTE bHardwareAddressType;
  397. BYTE pbHardwareAddress[0];
  398. } *pClientID;
  399. LPOPTION lpNewOption;
  400. pClientID = (_CLIENT_ID *) DhcpAllocateMemory( sizeof( struct _CLIENT_ID ) + ClientHWAddrLength );
  401. //
  402. // currently there is no way to indicate failure. simply return unmodified option
  403. // list
  404. //
  405. if ( !pClientID )
  406. return Option;
  407. pClientID->bHardwareAddressType = ClientHWType;
  408. memcpy( pClientID->pbHardwareAddress, ClientHWAddr, ClientHWAddrLength );
  409. lpNewOption = DhcpAppendOption(
  410. Option,
  411. OPTION_CLIENT_ID,
  412. (LPBYTE)pClientID,
  413. (BYTE)(ClientHWAddrLength + sizeof(BYTE)),
  414. OptionEnd );
  415. DhcpFreeMemory( pClientID );
  416. return lpNewOption;
  417. }
  418. // data locks on ClassesList must be taken before calling this function
  419. PDHCP_CLASSES PRIVATE // the required classes struct
  420. DhcpFindClass( // find a specified class
  421. IN OUT PLIST_ENTRY ClassesList, // list of classes to srch in
  422. IN LPBYTE Data, // non-NULL data bytes
  423. IN DWORD Len // # of bytes of above, > 0
  424. ) {
  425. PLIST_ENTRY ThisEntry;
  426. PDHCP_CLASSES ThisClass;
  427. ThisEntry = ClassesList->Flink; // first element in list
  428. while( ThisEntry != ClassesList ) { // search the full list
  429. ThisClass = CONTAINING_RECORD( ThisEntry, DHCP_CLASSES, ClassList );
  430. ThisEntry = ThisEntry->Flink;
  431. if( ThisClass->ClassLen == Len ) { // lengths must match
  432. if( ThisClass->ClassName == Data ) // data ptrs can match OR data can match
  433. return ThisClass;
  434. if( 0 == memcmp(ThisClass->ClassName, Data, Len) )
  435. return ThisClass;
  436. }
  437. }
  438. return NULL;
  439. }
  440. // locks on ClassesList should be taken when using this function
  441. LPBYTE // data bytes, or NULL
  442. DhcpAddClass( // add a new class
  443. IN OUT PLIST_ENTRY ClassesList, // list to add to
  444. IN LPBYTE Data, // input class name
  445. IN DWORD Len // # of bytes of above
  446. ) {
  447. PDHCP_CLASSES Class;
  448. DWORD MemSize; // amt of memory reqd
  449. if( NULL == ClassesList ) { // invalid parameter
  450. DhcpAssert( NULL != ClassesList );
  451. return NULL;
  452. }
  453. if( 0 == Len || NULL == Data ) { // invalid parameters
  454. DhcpAssert(0 != Len && NULL != Data );
  455. return NULL;
  456. }
  457. Class = DhcpFindClass(ClassesList,Data,Len); // already there in list?
  458. if(NULL != Class) { // yes, found
  459. Class->RefCount++; // increase ref-count
  460. return Class->ClassName;
  461. }
  462. MemSize = sizeof(*Class)+Len; // amt of memory reqd
  463. Class = (PDHCP_CLASSES) DhcpAllocateMemory(MemSize);
  464. if( NULL == Class ) { // not enough memory
  465. DhcpAssert( NULL != Class);
  466. return NULL;
  467. }
  468. Class->ClassLen = Len;
  469. Class->RefCount = 1;
  470. Class->ClassName = ((LPBYTE)Class) + sizeof(*Class);
  471. memcpy(Class->ClassName, Data, Len);
  472. InsertHeadList(ClassesList, &Class->ClassList);
  473. return Class->ClassName;
  474. }
  475. // locks on ClassesList must be taken before calling this function
  476. DWORD // status
  477. DhcpDelClass( // de-refernce a class
  478. IN OUT PLIST_ENTRY ClassesList, // the list to delete off
  479. IN LPBYTE Data, // the data ptr
  480. IN DWORD Len // the # of bytes of above
  481. ) {
  482. PDHCP_CLASSES Class;
  483. if( NULL == ClassesList ) {
  484. DhcpAssert( NULL != ClassesList );
  485. return ERROR_INVALID_PARAMETER;
  486. }
  487. if( 0 == Len || NULL == Data ) { // invalid parameter
  488. DhcpAssert( 0 != Len && NULL != Data );
  489. return ERROR_INVALID_PARAMETER;
  490. }
  491. Class = DhcpFindClass(ClassesList,Data,Len);
  492. if( NULL == Class ) { // did not find this class?
  493. DhcpAssert( NULL != Class );
  494. return ERROR_FILE_NOT_FOUND;
  495. }
  496. Class->RefCount --;
  497. if( 0 == Class->RefCount ) { // all references removed
  498. RemoveEntryList( &Class->ClassList ); // remove this from the list
  499. DhcpFreeMemory(Class); // free it
  500. }
  501. return ERROR_SUCCESS;
  502. }
  503. // locks on ClassesList must be taken before calling this function
  504. VOID // always succeed
  505. DhcpFreeAllClasses( // free each elt of the list
  506. IN OUT PLIST_ENTRY ClassesList // input list of classes
  507. ) {
  508. PDHCP_CLASSES ThisClass;
  509. PLIST_ENTRY ThisEntry;
  510. if( NULL == ClassesList ) {
  511. DhcpAssert( NULL != ClassesList && "DhcpFreeAllClasses" );
  512. return ;
  513. }
  514. while( !IsListEmpty(ClassesList) ) {
  515. ThisEntry = RemoveHeadList(ClassesList);
  516. ThisClass = CONTAINING_RECORD(ThisEntry, DHCP_CLASSES, ClassList);
  517. if( ThisClass->RefCount ) {
  518. DhcpPrint(("Freeing with refcount = %ld\n", ThisClass->RefCount));
  519. }
  520. DhcpFreeMemory(ThisClass);
  521. }
  522. InitializeListHead(ClassesList);
  523. }
  524. //--------------------------------------------------------------------------------
  525. // exported functions, options
  526. //--------------------------------------------------------------------------------
  527. // data locks need to be taken on OptionsList before calling this function
  528. PDHCP_OPTION // the reqd structure or NULL
  529. DhcpFindOption( // find a specific option
  530. IN OUT PLIST_ENTRY OptionsList, // the list of options to search
  531. IN BYTE OptionId, // the option id to search for
  532. IN BOOL IsVendor, // is it vendor specific?
  533. IN LPBYTE ClassName, // is there a class associated?
  534. IN DWORD ClassLen // # of bytes of above parameter
  535. ) {
  536. PLIST_ENTRY ThisEntry;
  537. PDHCP_OPTION ThisOption;
  538. if( NULL == OptionsList ) {
  539. DhcpAssert( NULL != OptionsList );
  540. return NULL;
  541. }
  542. ThisEntry = OptionsList->Flink;
  543. while( ThisEntry != OptionsList ) { // search the set of options
  544. ThisOption = CONTAINING_RECORD( ThisEntry, DHCP_OPTION, OptionList );
  545. ThisEntry = ThisEntry->Flink;
  546. if( ThisOption->OptionId != OptionId ) continue;
  547. if( ThisOption->IsVendor != IsVendor ) continue;
  548. if( ThisOption->ClassLen != ClassLen ) continue;
  549. if( ClassLen && ThisOption->ClassName != ClassName )
  550. continue; // mismatched so far
  551. return ThisOption; // found the option
  552. }
  553. return NULL; // did not find any match
  554. }
  555. // locks on OptionsList need to be taken before calling this function
  556. DWORD // status
  557. DhcpDelOption( // remove a particular option
  558. IN PDHCP_OPTION ThisOption // option to delete
  559. ) {
  560. if( NULL == ThisOption) // nope, did not find this option
  561. return ERROR_FILE_NOT_FOUND;
  562. RemoveEntryList( &ThisOption->OptionList); // found it. remove and free
  563. DhcpFreeMemory(ThisOption);
  564. return ERROR_SUCCESS;
  565. }
  566. // locks on OptionsList need to be taken before calling this function
  567. DWORD // status
  568. DhcpAddOption( // add a new option
  569. IN OUT PLIST_ENTRY OptionsList, // list to add to
  570. IN BYTE OptionId, // option id to add
  571. IN BOOL IsVendor, // is it vendor specific?
  572. IN LPBYTE ClassName, // what is the class?
  573. IN DWORD ClassLen, // size of above in bytes
  574. IN LPBYTE Data, // data for this option
  575. IN DWORD DataLen, // # of bytes of above
  576. IN time_t ExpiryTime // when the option expires
  577. ) {
  578. PDHCP_OPTION ThisOption;
  579. DWORD MemSize;
  580. if( NULL == OptionsList ) {
  581. DhcpAssert( NULL != OptionsList && "DhcpAddOption" );
  582. return ERROR_INVALID_PARAMETER;
  583. }
  584. if( 0 != ClassLen && NULL == ClassName ) {
  585. DhcpAssert( 0 == ClassLen || NULL != ClassName && "DhcpAddOption" );
  586. return ERROR_INVALID_PARAMETER;
  587. }
  588. if( 0 != DataLen && NULL == Data ) {
  589. DhcpAssert( 0 == DataLen || NULL != Data && "DhcpAddOption" );
  590. return ERROR_INVALID_PARAMETER;
  591. }
  592. MemSize = sizeof(DHCP_OPTION) + DataLen ;
  593. ThisOption = (PDHCP_OPTION) DhcpAllocateMemory(MemSize);
  594. if( NULL == ThisOption ) // could not allocate memory
  595. return ERROR_NOT_ENOUGH_MEMORY;
  596. ThisOption->OptionId = OptionId;
  597. ThisOption->IsVendor = IsVendor;
  598. ThisOption->ClassName = ClassName;
  599. ThisOption->ClassLen = ClassLen;
  600. ThisOption->ExpiryTime = ExpiryTime;
  601. ThisOption->DataLen = DataLen;
  602. ThisOption->Data = ((LPBYTE)ThisOption) + sizeof(DHCP_OPTION);
  603. memcpy(ThisOption->Data, Data, DataLen);
  604. InsertHeadList( OptionsList, &ThisOption->OptionList );
  605. return ERROR_SUCCESS;
  606. }
  607. //================================================================================
  608. // end of file
  609. //================================================================================