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.

570 lines
18 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcpdef.h
  5. Abstract:
  6. This module contains data type definitions for the DHCP client.
  7. Author:
  8. Madan Appiah (madana) 31-Oct-1993
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #ifndef _DHCPDEF_
  14. #define _DHCPDEF_
  15. //
  16. // the registry key is of different type between NT and Memphis.
  17. //
  18. #ifdef VXD
  19. typedef VMMHKEY DHCPKEY;
  20. #else // NT
  21. typedef HKEY DHCPKEY;
  22. #endif
  23. //
  24. // The amount of time to wait for a retry if we have no IP address
  25. //
  26. #define ADDRESS_ALLOCATION_RETRY 300 // 5 minutes
  27. #define EASYNET_ALLOCATION_RETRY 300 // 5 minutes
  28. //
  29. // The amount of time to wait for a retry if we have an IP address,
  30. // but the renewal on startup failed.
  31. //
  32. #if !DBG
  33. #define RENEWAL_RETRY 600 // 10 minutes
  34. #else
  35. #define RENEWAL_RETRY 60 // 1 minute
  36. #endif
  37. //
  38. // The number of times to send a request before giving up waiting
  39. // for a response.
  40. //
  41. #define DHCP_MAX_RETRIES 4
  42. #define DHCP_ACCEPT_RETRIES 2
  43. #define DHCP_MAX_RENEW_RETRIES 3
  44. //
  45. // amount of time required between consequtive send_informs..
  46. //
  47. #define DHCP_DEFAULT_INFORM_SEPARATION_INTERVAL 60 // one minute
  48. //
  49. // amount of time to wait after an address conflict is detected
  50. //
  51. #define ADDRESS_CONFLICT_RETRY 10 // 10 seconds
  52. //
  53. //
  54. // Expoenential backoff delay.
  55. //
  56. #define DHCP_EXPO_DELAY 4
  57. //
  58. // The maximum total amount of time to spend trying to obtain an
  59. // initial address.
  60. //
  61. // This delay is computed as below:
  62. //
  63. // DHCP_MAX_RETRIES - n
  64. // DHCP_EXPO_DELAY - m
  65. // WAIT_FOR_RESPONSE_TIME - w
  66. // MAX_STARTUP_DELAY - t
  67. //
  68. // Binary Exponential backup Algorithm.
  69. //
  70. // t > m * (n*(n+1)/2) + n + w*n
  71. // ------------------- ---
  72. // random wait + response wait
  73. //
  74. #define MAX_STARTUP_DELAY \
  75. DHCP_EXPO_DELAY * \
  76. (( DHCP_MAX_RETRIES * (DHCP_MAX_RETRIES + 1)) / 2) + \
  77. DHCP_MAX_RETRIES + DHCP_MAX_RETRIES * WAIT_FOR_RESPONSE_TIME
  78. #define MAX_RENEW_DELAY \
  79. DHCP_EXPO_DELAY * \
  80. (( DHCP_MAX_RENEW_RETRIES * (DHCP_MAX_RENEW_RETRIES + 1)) / 2) + \
  81. DHCP_MAX_RENEW_RETRIES + DHCP_MAX_RENEW_RETRIES * \
  82. WAIT_FOR_RESPONSE_TIME
  83. //
  84. // The maximum amount of time to wait between renewal retries, if the
  85. // lease period is between T1 and T2.
  86. //
  87. #define MAX_RETRY_TIME 3600 // 1 hour
  88. //
  89. // Minimum time to sleep between retries.
  90. //
  91. #if DBG
  92. #define MIN_SLEEP_TIME 1 // 1 sec.
  93. #else
  94. #define MIN_SLEEP_TIME 5 // 5 sec.
  95. #endif
  96. //
  97. // Minimum lease time.
  98. //
  99. #define DHCP_MINIMUM_LEASE 60*60 // 1 hours.
  100. #define DHCP_DNS_TTL 0 // let the DNS api decide..
  101. //
  102. // IP Autoconfiguration defaults
  103. //
  104. #define DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET "169.254.0.0"
  105. #define DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK "255.255.0.0"
  106. // define the reserved range of autonet addresses..
  107. #define DHCP_RESERVED_AUTOCFG_SUBNET "169.254.255.0"
  108. #define DHCP_RESERVED_AUTOCFG_MASK "255.255.255.0"
  109. // will dhcp pick any reserved autonet addr? NO!
  110. #define DHCP_RESERVED_AUTOCFG_FLAG (1)
  111. // self default route (0,0,<self>) will have a metric of (3)
  112. #define DHCP_SELF_DEFAULT_METRIC (3)
  113. //
  114. // General purpose macros
  115. //
  116. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  117. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  118. #if DBG
  119. #define STATIC
  120. #else
  121. #define STATIC static
  122. #endif
  123. #define LOCK_RENEW_LIST() EnterCriticalSection(&DhcpGlobalRenewListCritSect)
  124. #define UNLOCK_RENEW_LIST() LeaveCriticalSection(&DhcpGlobalRenewListCritSect)
  125. #define LOCK_INTERFACE() EnterCriticalSection(&DhcpGlobalSetInterfaceCritSect)
  126. #define UNLOCK_INTERFACE() LeaveCriticalSection(&DhcpGlobalSetInterfaceCritSect)
  127. #define LOCK_OPTIONS_LIST() EnterCriticalSection(&DhcpGlobalOptionsListCritSect)
  128. #define UNLOCK_OPTIONS_LIST() LeaveCriticalSection(&DhcpGlobalOptionsListCritSect)
  129. #define ZERO_TIME 0x0 // in secs.
  130. //
  131. // length of the time string returned by ctime.
  132. // actually it is 26.
  133. //
  134. #define TIME_STRING_LEN 32
  135. //
  136. // String size when a long converted to printable string.
  137. // 2^32 = 4294967295 (10 digits) + termination char.
  138. //
  139. #define LONG_STRING_SIZE 12
  140. //
  141. // A renewal function.
  142. //
  143. typedef
  144. DWORD
  145. (*PRENEWAL_FUNCTION) (
  146. IN PVOID Context,
  147. LPDWORD Sleep
  148. );
  149. //
  150. // DHCP Client-Identifier (option 61)
  151. //
  152. typedef struct _DHCP_CLIENT_IDENTIFIER
  153. {
  154. BYTE *pbID;
  155. DWORD cbID;
  156. BYTE bType;
  157. BOOL fSpecified;
  158. } DHCP_CLIENT_IDENTIFIER;
  159. //
  160. // state information for IP autoconfiguration
  161. //
  162. typedef struct _DHCP_IPAUTOCONFIGURATION_CONTEXT
  163. {
  164. DHCP_IP_ADDRESS Address;
  165. DHCP_IP_ADDRESS Subnet;
  166. DHCP_IP_ADDRESS Mask;
  167. DWORD Seed;
  168. } DHCP_IPAUTOCONFIGURATION_CONTEXT;
  169. //
  170. // A DHCP context block. One block is maintained per NIC (network
  171. // interface Card).
  172. //
  173. typedef struct _DHCP_CONTEXT {
  174. // list of adapters.
  175. LIST_ENTRY NicListEntry;
  176. // to place in renewal list.
  177. LIST_ENTRY RenewalListEntry;
  178. // Ref count
  179. LONG RefCount;
  180. // failed to renew because of lack of resources?
  181. BOOL bFailedRenewal;
  182. // hardware type.
  183. BYTE HardwareAddressType;
  184. // HW address, just follows this context structure.
  185. LPBYTE HardwareAddress;
  186. // Length of HW address.
  187. DWORD HardwareAddressLength;
  188. // Selected IpAddress, NetworkOrder.
  189. DHCP_IP_ADDRESS IpAddress;
  190. // Selected subnet mask. NetworkOrder.
  191. DHCP_IP_ADDRESS SubnetMask;
  192. // Selected DHCP server address. Network Order.
  193. DHCP_IP_ADDRESS DhcpServerAddress;
  194. // Desired IpAddress the client request in next discover.
  195. DHCP_IP_ADDRESS DesiredIpAddress;
  196. // The ip address that was used just before losing this..
  197. DHCP_IP_ADDRESS NackedIpAddress;
  198. // The ip address that just resulted in address conflict
  199. DHCP_IP_ADDRESS ConflictAddress;
  200. // The old metric for the default gateway. We receive it
  201. // through OPTION_MSFT_VENDOR_METRIC_BASE
  202. LONG OldDhcpMetricBase;
  203. // current domain name for this adapter.
  204. BYTE DomainName[260];
  205. // IP Autoconfiguration state
  206. DHCP_IPAUTOCONFIGURATION_CONTEXT IPAutoconfigurationContext;
  207. DHCP_CLIENT_IDENTIFIER ClientIdentifier;
  208. // Lease time in seconds.
  209. DWORD Lease;
  210. // Time the lease was obtained.
  211. time_t LeaseObtained;
  212. // Time the client should start renew its address.
  213. time_t T1Time;
  214. // Time the client should start broadcast to renew address.
  215. time_t T2Time;
  216. // Time the lease expires. The clinet should stop using the
  217. // IpAddress.
  218. // LeaseObtained < T1Time < T2Time < LeaseExpires
  219. time_t LeaseExpires;
  220. // when was the last time an inform was sent?
  221. time_t LastInformSent;
  222. // how many seconds between consecutive informs?
  223. DWORD InformSeparationInterval;
  224. // # of gateways and the currently plumbed gateways are stored here
  225. DWORD nGateways;
  226. DHCP_IP_ADDRESS *GatewayAddresses;
  227. // # of static routes and the actual static routes are stored here
  228. DWORD nStaticRoutes;
  229. DHCP_IP_ADDRESS *StaticRouteAddresses;
  230. // Time for next renewal state.
  231. time_t RunTime;
  232. // seconds passed since boot.
  233. DWORD SecondsSinceBoot;
  234. // should we ping the g/w or always assume g/w is NOT present?
  235. BOOL DontPingGatewayFlag;
  236. // can we use DHCP_INFORM packets or should we use DHCP_REQUEST instead?
  237. BOOL UseInformFlag;
  238. // Release on shutdown?
  239. ULONG ReleaseOnShutdown;
  240. // turn timers on off?
  241. BOOL fTimersEnabled;
  242. #ifdef BOOTPERF
  243. // allow saving of quickboot information?
  244. ULONG fQuickBootEnabled;
  245. #endif BOOTPERF
  246. // what to function at next renewal state.
  247. PRENEWAL_FUNCTION RenewalFunction;
  248. // A semaphore for synchronization to this structure
  249. HANDLE RenewHandle;
  250. // the list of options to send and the list of options received
  251. LIST_ENTRY SendOptionsList;
  252. LIST_ENTRY RecdOptionsList;
  253. // the list of options defining the fallback configuration
  254. LIST_ENTRY FbOptionsList;
  255. // the opened key to the adapter info storage location
  256. DHCPKEY AdapterInfoKey;
  257. // the class this adapter belongs to
  258. LPBYTE ClassId;
  259. DWORD ClassIdLength;
  260. // Message buffer to send and receive DHCP message.
  261. union {
  262. PDHCP_MESSAGE MessageBuffer;
  263. PMADCAP_MESSAGE MadcapMessageBuffer;
  264. };
  265. // state information for this interface. see below for manifests
  266. struct /* anonymous */ {
  267. unsigned Plumbed : 1 ; // is this interface plumbed
  268. unsigned ServerReached : 1 ; // Did we reach the server ever
  269. unsigned AutonetEnabled: 1 ; // Autonet enabled?
  270. unsigned HasBeenLooked : 1 ; // Has this context been looked at?
  271. unsigned DhcpEnabled : 1 ; // Is this context dhcp enabled?
  272. unsigned AutoMode : 1 ; // Currently in autonet mode?
  273. unsigned MediaState : 2 ; // One of connected, disconnected, reconnected, unbound
  274. unsigned MDhcp : 1 ; // Is this context created for Mdhcp?
  275. unsigned PowerResumed : 1 ; // Was power just resumed on this interface?
  276. unsigned Fallback : 1 ; // Is fallback configuration available?
  277. unsigned ApiContext : 1 ; // Is this context created by an API call?
  278. unsigned UniDirectional: 1 ; // Is this context created for a unidirectional adapter?
  279. } State;
  280. //
  281. // The following 2 fields are for the cancellation mechanism.
  282. //
  283. DWORD NumberOfWaitingThreads;
  284. WSAEVENT CancelEvent;
  285. // machine specific information
  286. PVOID LocalInformation;
  287. } DHCP_CONTEXT, *PDHCP_CONTEXT;
  288. #define ADDRESS_PLUMBED(Ctxt) ((Ctxt)->State.Plumbed = 1)
  289. #define ADDRESS_UNPLUMBED(Ctxt) ((Ctxt)->State.Plumbed = 0)
  290. #define IS_ADDRESS_PLUMBED(Ctxt) ((Ctxt)->State.Plumbed)
  291. #define IS_ADDRESS_UNPLUMBED(Ctxt) (!(Ctxt)->State.Plumbed)
  292. #define SERVER_REACHED(Ctxt) ((Ctxt)->State.ServerReached = 1)
  293. #define SERVER_UNREACHED(Ctxt) ((Ctxt)->State.ServerReached = 0)
  294. #define IS_SERVER_REACHABLE(Ctxt) ((Ctxt)->State.ServerReached)
  295. #define IS_SERVER_UNREACHABLE(Ctxt) (!(Ctxt)->State.ServerReached)
  296. #define AUTONET_ENABLED(Ctxt) ((Ctxt)->State.AutonetEnabled = 1)
  297. #define AUTONET_DISABLED(Ctxt) ((Ctxt)->State.AutonetEnabled = 0)
  298. #define IS_AUTONET_ENABLED(Ctxt) ((Ctxt)->State.AutonetEnabled)
  299. #define IS_AUTONET_DISABLED(Ctxt) (!(Ctxt)->State.AutonetEnabled)
  300. #define CTXT_WAS_LOOKED(Ctxt) ((Ctxt)->State.HasBeenLooked = 1)
  301. #define CTXT_WAS_NOT_LOOKED(Ctxt) ((Ctxt)->State.HasBeenLooked = 0)
  302. #define WAS_CTXT_LOOKED(Ctxt) ((Ctxt)->State.HasBeenLooked)
  303. #define WAS_CTXT_NOT_LOOKED(Ctxt) (!(Ctxt)->State.HasBeenLooked)
  304. #define DHCP_ENABLED(Ctxt) ((Ctxt)->State.DhcpEnabled = 1)
  305. #define DHCP_DISABLED(Ctxt) ((Ctxt)->State.DhcpEnabled = 0)
  306. #define IS_DHCP_ENABLED(Ctxt) ((Ctxt)->State.DhcpEnabled )
  307. #define IS_DHCP_DISABLED(Ctxt) (!(Ctxt)->State.DhcpEnabled )
  308. #define FALLBACK_ENABLED(Ctxt) ((Ctxt)->State.Fallback = 1)
  309. #define FALLBACK_DISABLED(Ctxt) ((Ctxt)->State.Fallback = 0)
  310. #define IS_FALLBACK_ENABLED(Ctxt) ((Ctxt)->State.Fallback)
  311. #define IS_FALLBACK_DISABLED(Ctxt) (!(Ctxt)->State.Fallback)
  312. #define APICTXT_ENABLED(Ctxt) ((Ctxt)->State.ApiContext = 1)
  313. #define APICTXT_DISABLED(Ctxt) ((Ctxt)->State.ApiContext = 0)
  314. #define IS_APICTXT_ENABLED(Ctxt) ((Ctxt)->State.ApiContext)
  315. #define IS_APICTXT_DISABLED(Ctxt) (!(Ctxt)->State.ApiContext)
  316. #define IS_UNIDIRECTIONAL(Ctxt) ((Ctxt)->State.UniDirectional)
  317. //
  318. // DNS resolver uses these without defines. So, don't change them.
  319. //
  320. #define ADDRESS_TYPE_AUTO 1
  321. #define ADDRESS_TYPE_DHCP 0
  322. #define ACQUIRED_DHCP_ADDRESS(Ctxt) ((Ctxt)->State.AutoMode = 0 )
  323. #define ACQUIRED_AUTO_ADDRESS(Ctxt) ((Ctxt)->State.AutoMode = 1 )
  324. #define IS_ADDRESS_DHCP(Ctxt) (!(Ctxt)->State.AutoMode)
  325. #define IS_ADDRESS_AUTO(Ctxt) ((Ctxt)->State.AutoMode)
  326. #define MEDIA_CONNECTED(Ctxt) ((Ctxt)->State.MediaState = 0)
  327. #define MEDIA_RECONNECTED(Ctxt) ((Ctxt)->State.MediaState = 1)
  328. #define MEDIA_DISCONNECTED(Ctxt) ((Ctxt)->State.MediaState = 2)
  329. #define MEDIA_UNBOUND(Ctxt) ((Ctxt)->State.MediaState = 3)
  330. #define IS_MEDIA_CONNECTED(Ctxt) ((Ctxt)->State.MediaState == 0)
  331. #define IS_MEDIA_RECONNECTED(Ctxt) ((Ctxt)->State.MediaState == 1)
  332. #define IS_MEDIA_DISCONNECTED(Ctxt) ((Ctxt)->State.MediaState == 2)
  333. #define IS_MEDIA_UNBOUND(Ctxt) ((Ctxt)->State.MediaState == 3)
  334. #define _INIT_STATE1(Ctxt) do{(Ctxt)->State.Plumbed = 0; (Ctxt)->State.AutonetEnabled=0;}while(0)
  335. #define _INIT_STATE2(Ctxt) do{(Ctxt)->State.HasBeenLooked = 0; (Ctxt)->State.DhcpEnabled=1;}while(0)
  336. #define _INIT_STATE3(Ctxt) do{(Ctxt)->State.AutoMode = 0; (Ctxt)->State.MediaState = 0;}while(0)
  337. #define INIT_STATE(Ctxt) do{_INIT_STATE1(Ctxt);_INIT_STATE2(Ctxt);_INIT_STATE3(Ctxt);}while(0)
  338. #define MDHCP_CTX(Ctxt) ((Ctxt)->State.MDhcp = 1)
  339. #define NONMDHCP_CTX(Ctxt) ((Ctxt)->State.MDhcp = 0)
  340. #define IS_MDHCP_CTX(Ctxt) ((Ctxt)->State.MDhcp )
  341. #define SET_MDHCP_STATE( Ctxt ) { \
  342. ADDRESS_PLUMBED( Ctxt ), MDHCP_CTX( Ctxt ); \
  343. }
  344. #define POWER_RESUMED(Ctxt) ((Ctxt)->State.PowerResumed = 1)
  345. #define POWER_NOT_RESUMED(Ctxt) ((Ctxt)->State.PowerResumed = 0)
  346. #define IS_POWER_RESUMED(Ctxt) ((Ctxt)->State.PowerResumed )
  347. LPSTR _inline // the string'ed version of state (same as Buffer)
  348. ConvertStateToString( // convert from bits to string
  349. IN PDHCP_CONTEXT Ctxt, // The context to print state for
  350. IN LPBYTE Buffer // The input buffer to write state into
  351. ) {
  352. strcpy(Buffer, IS_DHCP_ENABLED(Ctxt)?"DhcpEnabled ":"DhcpDisabled ");
  353. strcat(Buffer, IS_AUTONET_ENABLED(Ctxt)?"AutonetEnabled ":"AutonetDisabled ");
  354. strcat(Buffer, IS_ADDRESS_DHCP(Ctxt)?"DhcpMode ":"AutoMode ");
  355. strcat(Buffer, IS_ADDRESS_PLUMBED(Ctxt)?"Plumbed ":"UnPlumbed ");
  356. strcat(Buffer, IS_SERVER_REACHABLE(Ctxt)?"(server-present) ":"(server-absent) ");
  357. strcat(Buffer, WAS_CTXT_LOOKED(Ctxt)? "(seen) ":"(not-seen) ");
  358. if(IS_MEDIA_CONNECTED(Ctxt) ) strcat(Buffer, "MediaConnected\n");
  359. else if(IS_MEDIA_RECONNECTED(Ctxt)) strcat(Buffer, "MediaReConnected\n");
  360. else if(IS_MEDIA_DISCONNECTED(Ctxt)) strcat(Buffer, "MediaDisConnected\n");
  361. else strcat(Buffer, "MediaUnknownState\n");
  362. strcat(Buffer, IS_MDHCP_CTX(Ctxt)? "(MDhcp) ":"");
  363. strcat(Buffer, IS_POWER_RESUMED(Ctxt)? "Pwr Resumed ":"");
  364. return Buffer;
  365. }
  366. //
  367. // Release on shutdown values..
  368. //
  369. #define RELEASE_ON_SHUTDOWN_OBEY_DHCP_SERVER 2
  370. #define RELEASE_ON_SHUTDOWN_ALWAYS 1
  371. #define RELEASE_ON_SHUTDOWN_NEVER 0
  372. //
  373. // The types of machines.. laptop would have aggressive EASYNET behaviour.
  374. //
  375. #define MACHINE_NONE 0
  376. #define MACHINE_LAPTOP 1
  377. //
  378. // Here is the set of options understood by the client
  379. //
  380. typedef struct _DHCP_FULL_OPTIONS {
  381. BYTE UNALIGNED* MessageType; // What kind of message is this?
  382. BYTE UNALIGNED* AutoconfOption;
  383. // Basic IP Parameters
  384. DHCP_IP_ADDRESS UNALIGNED* SubnetMask;
  385. DHCP_IP_ADDRESS UNALIGNED* LeaseTime;
  386. DHCP_IP_ADDRESS UNALIGNED* T1Time;
  387. DHCP_IP_ADDRESS UNALIGNED* T2Time;
  388. DHCP_IP_ADDRESS UNALIGNED* GatewayAddresses;
  389. DWORD nGateways;
  390. DHCP_IP_ADDRESS UNALIGNED* ClassedRouteAddresses;
  391. DWORD nClassedRoutes;
  392. BYTE UNALIGNED* ClasslessRouteAddresses;
  393. DWORD nClasslessRoutes;
  394. DHCP_IP_ADDRESS UNALIGNED* ServerIdentifier;
  395. // DNS parameters
  396. BYTE UNALIGNED* DnsFlags;
  397. BYTE UNALIGNED* DnsRcode1;
  398. BYTE UNALIGNED* DnsRcode2;
  399. BYTE UNALIGNED* DomainName;
  400. DWORD DomainNameSize;
  401. DHCP_IP_ADDRESS UNALIGNED* DnsServerList;
  402. DWORD nDnsServers;
  403. // Server message is something that the server may inform us of
  404. BYTE UNALIGNED* ServerMessage;
  405. DWORD ServerMessageLength;
  406. } DHCP_FULL_OPTIONS, *PDHCP_FULL_OPTIONS, *LPDHCP_FULL_OPTIONS;
  407. typedef DHCP_FULL_OPTIONS DHCP_OPTIONS, *PDHCP_OPTIONS;
  408. typedef struct _MADCAP_OPTIONS {
  409. DWORD UNALIGNED* LeaseTime;
  410. DWORD UNALIGNED* Time;
  411. DWORD UNALIGNED* RetryTime;
  412. DHCP_IP_ADDRESS UNALIGNED* ServerIdentifier;
  413. BYTE * ClientGuid;
  414. WORD ClientGuidLength;
  415. BYTE * MScopeList;
  416. WORD MScopeListLength;
  417. DWORD UNALIGNED* MCastLeaseStartTime;
  418. BYTE * AddrRangeList;
  419. WORD AddrRangeListSize;
  420. DWORD UNALIGNED* McastScope;
  421. DWORD UNALIGNED* Error;
  422. } MADCAP_OPTIONS, *PMADCAP_OPTIONS, *LPMADCAP_OPTIONS;
  423. //
  424. // structure for a list of messages
  425. //
  426. typedef struct _MSG_LIST {
  427. LIST_ENTRY MessageListEntry;
  428. DWORD ServerIdentifier;
  429. DWORD MessageSize;
  430. DWORD LeaseExpirationTime;
  431. DHCP_MESSAGE Message;
  432. } MSGLIST, *PMSGLIST, *LPMSGLIST;
  433. //
  434. // structure for IP/Subnet pair
  435. //
  436. typedef struct {
  437. DHCP_IP_ADDRESS IpAddress;
  438. DHCP_IP_ADDRESS SubnetMask;
  439. } IP_SUBNET, *PIP_SUBNET;
  440. #endif // _DHCPDEF_