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.

779 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. UNREFERENCED_PARAMETER(DhcpContext);
  63. Size = FirstSize = 0;
  64. Buffer[Size++] = OPTION_SUBNET_MASK; // standard requested options
  65. Buffer[Size++] = OPTION_DOMAIN_NAME;
  66. Buffer[Size++] = OPTION_ROUTER_ADDRESS;
  67. Buffer[Size++] = OPTION_DOMAIN_NAME_SERVERS;
  68. Buffer[Size++] = OPTION_NETBIOS_NAME_SERVER;
  69. Buffer[Size++] = OPTION_NETBIOS_NODE_TYPE;
  70. Buffer[Size++] = OPTION_NETBIOS_SCOPE_OPTION;
  71. Buffer[Size++] = OPTION_VENDOR_SPEC_INFO;
  72. Buffer[Size++] = OPTION_USER_CLASS;
  73. Buffer[Size++] = OPTION_WPAD_URL;
  74. ThisEntry = SendOptionsList->Flink;
  75. while( ThisEntry != SendOptionsList ) {
  76. ThisOpt = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
  77. ThisEntry = ThisEntry->Flink;
  78. if( ThisOpt->IsVendor) continue;
  79. if( ThisOpt->ClassLen ) {
  80. if( ThisOpt->ClassLen != ClassLen ) continue;
  81. if( ThisOpt->ClassName != ClassName )
  82. continue; // this option is not used for this client
  83. }
  84. if( OPTION_PARAMETER_REQUEST_LIST != ThisOpt->OptionId ) {
  85. //
  86. // only if the option is param_request_list do we request..
  87. //
  88. continue;
  89. }
  90. for( i = 0; i < ThisOpt->DataLen ; i ++ ) {
  91. for( j = 0; j < Size; j ++ )
  92. if( ThisOpt->Data[i] == Buffer[j] ) break;
  93. if( j < Size ) continue; // option already plugged in
  94. Buffer[Size++] = ThisOpt->Data[i]; // add this option
  95. }
  96. if( 0 == FirstSize ) FirstSize = Size;
  97. }
  98. if( 0 == FirstSize ) FirstSize = Size;
  99. Tmp = BufStart;
  100. BufStart = (LPBYTE)DhcpAppendOption( // now add the param request list
  101. (POPTION)BufStart,
  102. (BYTE)OPTION_PARAMETER_REQUEST_LIST,
  103. Buffer,
  104. (BYTE)Size,
  105. BufEnd
  106. );
  107. if( Tmp == BufStart ) { // did not really add the option
  108. BufStart = (LPBYTE)DhcpAppendOption( // now try adding the first request we saw instead of everything
  109. (POPTION)BufStart,
  110. (BYTE)OPTION_PARAMETER_REQUEST_LIST,
  111. Buffer,
  112. (BYTE)FirstSize,
  113. BufEnd
  114. );
  115. }
  116. return BufStart;
  117. }
  118. POPTION // option from which more appends can occur
  119. DhcpAppendSendOptions( // append all configured options
  120. IN OUT PDHCP_CONTEXT DhcpContext, // this is the context to append for
  121. IN PLIST_ENTRY SendOptionsList,
  122. IN LPBYTE ClassName, // current class
  123. IN DWORD ClassLen, // len of above in bytes
  124. IN LPBYTE BufStart, // start of buffer
  125. IN LPBYTE BufEnd, // how far can we go in this buffer
  126. IN OUT LPBYTE SentOptions, // BoolArray[OPTION_END+1] to avoid repeating options
  127. IN OUT LPBYTE VSentOptions, // to avoid repeating vendor specific options
  128. IN OUT LPBYTE VendorOpt, // Buffer[OPTION_END+1] Holding Vendor specific options
  129. OUT LPDWORD VendorOptLen // the # of bytes filled into that
  130. ) {
  131. PLIST_ENTRY ThisEntry;
  132. PDHCP_OPTION ThisOpt;
  133. DhcpAssert(FALSE == SentOptions[OPTION_PARAMETER_REQUEST_LIST]);
  134. BufStart = DhcpAppendParamRequestList(
  135. DhcpContext,
  136. SendOptionsList,
  137. ClassName,
  138. ClassLen,
  139. BufStart,
  140. BufEnd
  141. );
  142. SentOptions[OPTION_PARAMETER_REQUEST_LIST] = TRUE;
  143. ThisEntry = SendOptionsList->Flink;
  144. while( ThisEntry != SendOptionsList ) {
  145. ThisOpt = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
  146. ThisEntry = ThisEntry->Flink;
  147. if( ThisOpt->IsVendor ? VSentOptions[ThisOpt->OptionId] : SentOptions[ThisOpt->OptionId] )
  148. continue;
  149. // if( ThisOpt->IsVendor) continue; // No vendor specific information this round through
  150. if( ThisOpt->ClassLen ) {
  151. if( ThisOpt->ClassLen != ClassLen ) continue;
  152. if( ThisOpt->ClassName != ClassName )
  153. continue; // this option is not used for this client
  154. }
  155. if( !ThisOpt->IsVendor ) { // easy to add non-vendor spec options
  156. SentOptions[ThisOpt->OptionId] = TRUE;
  157. BufStart = (LPBYTE)DhcpAppendOption(
  158. (POPTION)BufStart,
  159. ThisOpt->OptionId,
  160. ThisOpt->Data,
  161. (BYTE)ThisOpt->DataLen,
  162. BufEnd
  163. );
  164. } else { // ENCAPSULATE vendor specific options
  165. if( SentOptions[OPTION_VENDOR_SPEC_INFO] )
  166. continue; // Vendor spec info already added
  167. VSentOptions[ThisOpt->OptionId] = TRUE;
  168. if( ThisOpt->DataLen + 2 + *VendorOptLen > OPTION_END )
  169. continue; // this option overflows the buffer
  170. VendorOpt[(*VendorOptLen)++] = ThisOpt->OptionId;
  171. VendorOpt[(*VendorOptLen)++] = (BYTE)ThisOpt->DataLen;
  172. memcpy(&VendorOpt[*VendorOptLen], ThisOpt->Data, ThisOpt->DataLen);
  173. (*VendorOptLen) += ThisOpt->DataLen;
  174. }
  175. }
  176. return (POPTION)BufStart;
  177. }
  178. DWORD // status
  179. DhcpDestroyOptionsList( // destroy a list of options, freeing up memory
  180. IN OUT PLIST_ENTRY OptionsList, // this is the list of options to destroy
  181. IN PLIST_ENTRY ClassesList // this is where to remove classes off
  182. ) {
  183. PLIST_ENTRY ThisEntry;
  184. PDHCP_OPTION ThisOption;
  185. DWORD Error;
  186. DWORD LastError;
  187. LastError = ERROR_SUCCESS;
  188. while(!IsListEmpty(OptionsList) ) { // for each element of this list
  189. ThisEntry = RemoveHeadList(OptionsList);
  190. ThisOption = CONTAINING_RECORD(ThisEntry, DHCP_OPTION, OptionList);
  191. if( NULL != ThisOption->ClassName ) { // if there is a class, deref it
  192. Error = DhcpDelClass(
  193. ClassesList,
  194. ThisOption->ClassName,
  195. ThisOption->ClassLen
  196. );
  197. if( ERROR_SUCCESS != Error ) {
  198. DhcpAssert( ERROR_SUCCESS == Error);
  199. LastError = Error;
  200. }
  201. }
  202. DhcpFreeMemory(ThisOption); // now really free this
  203. }
  204. return LastError;
  205. }
  206. DWORD // win32 status
  207. DhcpClearAllOptions( // clear all the options information
  208. IN OUT PDHCP_CONTEXT DhcpContext // the context to clear for
  209. ) {
  210. PLIST_ENTRY ThisEntry;
  211. PDHCP_OPTION ThisOption;
  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(push) // save current warning state
  395. #pragma warning(disable : 4200) // disable 0-sized array warning
  396. struct _CLIENT_ID {
  397. BYTE bHardwareAddressType;
  398. BYTE pbHardwareAddress[0];
  399. } *pClientID;
  400. #pragma warning(pop) // restore previous warning state
  401. LPOPTION lpNewOption;
  402. pClientID = (_CLIENT_ID *) DhcpAllocateMemory( sizeof( struct _CLIENT_ID ) + ClientHWAddrLength );
  403. //
  404. // currently there is no way to indicate failure. simply return unmodified option
  405. // list
  406. //
  407. if ( !pClientID )
  408. return Option;
  409. pClientID->bHardwareAddressType = ClientHWType;
  410. memcpy( pClientID->pbHardwareAddress, ClientHWAddr, ClientHWAddrLength );
  411. lpNewOption = DhcpAppendOption(
  412. Option,
  413. OPTION_CLIENT_ID,
  414. (LPBYTE)pClientID,
  415. (BYTE)(ClientHWAddrLength + sizeof(BYTE)),
  416. OptionEnd );
  417. DhcpFreeMemory( pClientID );
  418. return lpNewOption;
  419. }
  420. // data locks on ClassesList must be taken before calling this function
  421. PDHCP_CLASSES PRIVATE // the required classes struct
  422. DhcpFindClass( // find a specified class
  423. IN OUT PLIST_ENTRY ClassesList, // list of classes to srch in
  424. IN LPBYTE Data, // non-NULL data bytes
  425. IN DWORD Len // # of bytes of above, > 0
  426. ) {
  427. PLIST_ENTRY ThisEntry;
  428. PDHCP_CLASSES ThisClass;
  429. ThisEntry = ClassesList->Flink; // first element in list
  430. while( ThisEntry != ClassesList ) { // search the full list
  431. ThisClass = CONTAINING_RECORD( ThisEntry, DHCP_CLASSES, ClassList );
  432. ThisEntry = ThisEntry->Flink;
  433. if( ThisClass->ClassLen == Len ) { // lengths must match
  434. if( ThisClass->ClassName == Data ) // data ptrs can match OR data can match
  435. return ThisClass;
  436. if( 0 == memcmp(ThisClass->ClassName, Data, Len) )
  437. return ThisClass;
  438. }
  439. }
  440. return NULL;
  441. }
  442. // locks on ClassesList should be taken when using this function
  443. LPBYTE // data bytes, or NULL
  444. DhcpAddClass( // add a new class
  445. IN OUT PLIST_ENTRY ClassesList, // list to add to
  446. IN LPBYTE Data, // input class name
  447. IN DWORD Len // # of bytes of above
  448. ) {
  449. PDHCP_CLASSES Class;
  450. DWORD MemSize; // amt of memory reqd
  451. if( NULL == ClassesList ) { // invalid parameter
  452. DhcpAssert( NULL != ClassesList );
  453. return NULL;
  454. }
  455. if( 0 == Len || NULL == Data ) { // invalid parameters
  456. DhcpAssert(0 != Len && NULL != Data );
  457. return NULL;
  458. }
  459. Class = DhcpFindClass(ClassesList,Data,Len); // already there in list?
  460. if(NULL != Class) { // yes, found
  461. Class->RefCount++; // increase ref-count
  462. return Class->ClassName;
  463. }
  464. MemSize = sizeof(*Class)+Len; // amt of memory reqd
  465. Class = (PDHCP_CLASSES) DhcpAllocateMemory(MemSize);
  466. if( NULL == Class ) { // not enough memory
  467. DhcpAssert( NULL != Class);
  468. return NULL;
  469. }
  470. Class->ClassLen = Len;
  471. Class->RefCount = 1;
  472. Class->ClassName = ((LPBYTE)Class) + sizeof(*Class);
  473. memcpy(Class->ClassName, Data, Len);
  474. InsertHeadList(ClassesList, &Class->ClassList);
  475. return Class->ClassName;
  476. }
  477. // locks on ClassesList must be taken before calling this function
  478. DWORD // status
  479. DhcpDelClass( // de-refernce a class
  480. IN OUT PLIST_ENTRY ClassesList, // the list to delete off
  481. IN LPBYTE Data, // the data ptr
  482. IN DWORD Len // the # of bytes of above
  483. ) {
  484. PDHCP_CLASSES Class;
  485. if( NULL == ClassesList ) {
  486. DhcpAssert( NULL != ClassesList );
  487. return ERROR_INVALID_PARAMETER;
  488. }
  489. if( 0 == Len || NULL == Data ) { // invalid parameter
  490. DhcpAssert( 0 != Len && NULL != Data );
  491. return ERROR_INVALID_PARAMETER;
  492. }
  493. Class = DhcpFindClass(ClassesList,Data,Len);
  494. if( NULL == Class ) { // did not find this class?
  495. DhcpAssert( NULL != Class );
  496. return ERROR_FILE_NOT_FOUND;
  497. }
  498. Class->RefCount --;
  499. if( 0 == Class->RefCount ) { // all references removed
  500. RemoveEntryList( &Class->ClassList ); // remove this from the list
  501. DhcpFreeMemory(Class); // free it
  502. }
  503. return ERROR_SUCCESS;
  504. }
  505. // locks on ClassesList must be taken before calling this function
  506. VOID // always succeed
  507. DhcpFreeAllClasses( // free each elt of the list
  508. IN OUT PLIST_ENTRY ClassesList // input list of classes
  509. ) {
  510. PDHCP_CLASSES ThisClass;
  511. PLIST_ENTRY ThisEntry;
  512. if( NULL == ClassesList ) {
  513. DhcpAssert( NULL != ClassesList && "DhcpFreeAllClasses" );
  514. return ;
  515. }
  516. while( !IsListEmpty(ClassesList) ) {
  517. ThisEntry = RemoveHeadList(ClassesList);
  518. ThisClass = CONTAINING_RECORD(ThisEntry, DHCP_CLASSES, ClassList);
  519. if( ThisClass->RefCount ) {
  520. DhcpPrint(("Freeing with refcount = %ld\n", ThisClass->RefCount));
  521. }
  522. DhcpFreeMemory(ThisClass);
  523. }
  524. InitializeListHead(ClassesList);
  525. }
  526. //--------------------------------------------------------------------------------
  527. // exported functions, options
  528. //--------------------------------------------------------------------------------
  529. // data locks need to be taken on OptionsList before calling this function
  530. PDHCP_OPTION // the reqd structure or NULL
  531. DhcpFindOption( // find a specific option
  532. IN OUT PLIST_ENTRY OptionsList, // the list of options to search
  533. IN BYTE OptionId, // the option id to search for
  534. IN BOOL IsVendor, // is it vendor specific?
  535. IN LPBYTE ClassName, // is there a class associated?
  536. IN DWORD ClassLen // # of bytes of above parameter
  537. ) {
  538. PLIST_ENTRY ThisEntry;
  539. PDHCP_OPTION ThisOption;
  540. if( NULL == OptionsList ) {
  541. DhcpAssert( NULL != OptionsList );
  542. return NULL;
  543. }
  544. ThisEntry = OptionsList->Flink;
  545. while( ThisEntry != OptionsList ) { // search the set of options
  546. ThisOption = CONTAINING_RECORD( ThisEntry, DHCP_OPTION, OptionList );
  547. ThisEntry = ThisEntry->Flink;
  548. if( ThisOption->OptionId != OptionId ) continue;
  549. if( ThisOption->IsVendor != IsVendor ) continue;
  550. if( ThisOption->ClassLen != ClassLen ) continue;
  551. if( ClassLen && ThisOption->ClassName != ClassName )
  552. continue; // mismatched so far
  553. return ThisOption; // found the option
  554. }
  555. return NULL; // did not find any match
  556. }
  557. // locks on OptionsList need to be taken before calling this function
  558. DWORD // status
  559. DhcpDelOption( // remove a particular option
  560. IN PDHCP_OPTION ThisOption // option to delete
  561. ) {
  562. if( NULL == ThisOption) // nope, did not find this option
  563. return ERROR_FILE_NOT_FOUND;
  564. RemoveEntryList( &ThisOption->OptionList); // found it. remove and free
  565. DhcpFreeMemory(ThisOption);
  566. return ERROR_SUCCESS;
  567. }
  568. // locks on OptionsList need to be taken before calling this function
  569. DWORD // status
  570. DhcpAddOption( // add a new option
  571. IN OUT PLIST_ENTRY OptionsList, // list to add to
  572. IN BYTE OptionId, // option id to add
  573. IN BOOL IsVendor, // is it vendor specific?
  574. IN LPBYTE ClassName, // what is the class?
  575. IN DWORD ClassLen, // size of above in bytes
  576. IN LPBYTE Data, // data for this option
  577. IN DWORD DataLen, // # of bytes of above
  578. IN time_t ExpiryTime // when the option expires
  579. ) {
  580. PDHCP_OPTION ThisOption;
  581. DWORD MemSize;
  582. if( NULL == OptionsList ) {
  583. DhcpAssert( NULL != OptionsList && "DhcpAddOption" );
  584. return ERROR_INVALID_PARAMETER;
  585. }
  586. if( 0 != ClassLen && NULL == ClassName ) {
  587. DhcpAssert( 0 == ClassLen || NULL != ClassName && "DhcpAddOption" );
  588. return ERROR_INVALID_PARAMETER;
  589. }
  590. if( 0 != DataLen && NULL == Data ) {
  591. DhcpAssert( 0 == DataLen || NULL != Data && "DhcpAddOption" );
  592. return ERROR_INVALID_PARAMETER;
  593. }
  594. MemSize = sizeof(DHCP_OPTION) + DataLen ;
  595. ThisOption = (PDHCP_OPTION) DhcpAllocateMemory(MemSize);
  596. if( NULL == ThisOption ) // could not allocate memory
  597. return ERROR_NOT_ENOUGH_MEMORY;
  598. ThisOption->OptionId = OptionId;
  599. ThisOption->IsVendor = IsVendor;
  600. ThisOption->ClassName = ClassName;
  601. ThisOption->ClassLen = ClassLen;
  602. ThisOption->ExpiryTime = ExpiryTime;
  603. ThisOption->DataLen = DataLen;
  604. ThisOption->Data = ((LPBYTE)ThisOption) + sizeof(DHCP_OPTION);
  605. memcpy(ThisOption->Data, Data, DataLen);
  606. InsertHeadList( OptionsList, &ThisOption->OptionList );
  607. return ERROR_SUCCESS;
  608. }
  609. //================================================================================
  610. // end of file
  611. //================================================================================