Source code of Windows XP (NT5)
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.

556 lines
13 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcpcom.c
  5. Abstract:
  6. This module contains OS independent routines
  7. Author:
  8. John Ludeman (johnl) 13-Nov-1993
  9. Broke out independent routines from existing files
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <dhcpl.h>
  16. LPOPTION
  17. DhcpAppendOption(
  18. LPOPTION Option,
  19. BYTE OptionType,
  20. PVOID OptionValue,
  21. ULONG OptionLength,
  22. LPBYTE OptionEnd
  23. )
  24. /*++
  25. Routine Description:
  26. This function writes a DHCP option to message buffer.
  27. Arguments:
  28. Option - A pointer to a message buffer.
  29. OptionType - The option number to append.
  30. OptionValue - A pointer to the option data.
  31. OptionLength - The lenght, in bytes, of the option data.
  32. OptionEnd - End of Option Buffer.
  33. Return Value:
  34. A pointer to the end of the appended option.
  35. --*/
  36. {
  37. DWORD i;
  38. if ( OptionType == OPTION_END ) {
  39. //
  40. // we should alway have atleast one BYTE space in the buffer
  41. // to append this option.
  42. //
  43. DhcpAssert( (LPBYTE)Option < OptionEnd );
  44. Option->OptionType = OPTION_END;
  45. return( (LPOPTION) ((LPBYTE)(Option) + 1) );
  46. }
  47. if ( OptionType == OPTION_PAD ) {
  48. //
  49. // add this option only iff we have enough space in the buffer.
  50. //
  51. if(((LPBYTE)Option + 1) < (OptionEnd - 1) ) {
  52. Option->OptionType = OPTION_PAD;
  53. return( (LPOPTION) ((LPBYTE)(Option) + 1) );
  54. }
  55. DhcpPrint(( 0, "DhcpAppendOption failed to append Option "
  56. "%ld, Buffer too small.\n", OptionType ));
  57. return Option;
  58. }
  59. //
  60. // add this option only iff we have enough space in the buffer.
  61. //
  62. if(((LPBYTE)Option + 2 + OptionLength) >= (OptionEnd - 1) ) {
  63. DhcpPrint(( 0, "DhcpAppendOption failed to append Option "
  64. "%ld, Buffer too small.\n", OptionType ));
  65. return Option;
  66. }
  67. if( OptionLength <= 0xFF ) {
  68. // simple option.. no need to use OPTION_MSFT_CONTINUED
  69. Option->OptionType = OptionType;
  70. Option->OptionLength = (BYTE)OptionLength;
  71. memcpy( Option->OptionValue, OptionValue, OptionLength );
  72. return( (LPOPTION) ((LPBYTE)(Option) + Option->OptionLength + 2) );
  73. }
  74. // option size is > 0xFF --> need to continue it using multiple ones..
  75. // there are OptionLenght / 0xFF occurances using 0xFF+2 bytes + one
  76. // using 2 + (OptionLength % 0xFF ) space..
  77. // check to see if we have the space first..
  78. if( 2 + (OptionLength%0xFF) + 0x101*(OptionLength/0xFF)
  79. + (LPBYTE)Option >= (OptionEnd - 1) ) {
  80. DhcpPrint(( 0, "DhcpAppendOption failed to append Option "
  81. "%ld, Buffer too small.\n", OptionType ));
  82. return Option;
  83. }
  84. // first finish off all chunks of 0xFF size that we can do..
  85. i = OptionLength/0xFF;
  86. while(i --) {
  87. Option->OptionType = OptionType;
  88. Option->OptionLength = 0xFF;
  89. memcpy(Option->OptionValue, OptionValue, 0xFF);
  90. OptionValue = 0xFF+(LPBYTE)OptionValue;
  91. Option = (LPOPTION)(0x101 + (LPBYTE)Option);
  92. OptionType = OPTION_MSFT_CONTINUED; // all but the first use this ...
  93. OptionLength -= 0xFF;
  94. }
  95. // now finish off the remaining stuff..
  96. DhcpAssert(OptionLength <= 0xFF);
  97. Option->OptionType = OPTION_MSFT_CONTINUED;
  98. Option->OptionLength = (BYTE)OptionLength;
  99. memcpy(Option->OptionValue, OptionValue, OptionLength);
  100. Option = (LPOPTION)(2 + OptionLength + (LPBYTE)Option);
  101. DhcpAssert((LPBYTE)Option < OptionEnd);
  102. return Option;
  103. }
  104. WIDE_OPTION UNALIGNED *
  105. AppendWideOption(
  106. WIDE_OPTION UNALIGNED *Option,
  107. WORD OptionType,
  108. PVOID OptionValue,
  109. WORD OptionLength,
  110. LPBYTE OptionEnd
  111. )
  112. /*++
  113. Routine Description:
  114. This function writes a DHCP option to message buffer.
  115. Arguments:
  116. Option - A pointer to a message buffer.
  117. OptionType - The option number to append.
  118. OptionValue - A pointer to the option data.
  119. OptionLength - The lenght, in bytes, of the option data.
  120. OptionEnd - End of Option Buffer.
  121. Return Value:
  122. A pointer to the end of the appended option.
  123. --*/
  124. {
  125. DWORD i;
  126. //
  127. // add this option only iff we have enough space in the buffer.
  128. //
  129. if(((LPBYTE)&Option->OptionValue + OptionLength) >= (OptionEnd - FIELD_OFFSET(WIDE_OPTION, OptionValue)) ) {
  130. DhcpPrint(( 0, "AppendWideOption failed to append Option "
  131. "%ld, Buffer too small.\n", OptionType ));
  132. return Option;
  133. }
  134. Option->OptionType = ntohs(OptionType);
  135. Option->OptionLength = ntohs(OptionLength);
  136. memcpy(Option->OptionValue, OptionValue, OptionLength);
  137. Option = (WIDE_OPTION UNALIGNED *)((PBYTE)&Option->OptionValue + OptionLength );
  138. DhcpAssert((LPBYTE)Option < OptionEnd);
  139. return Option;
  140. }
  141. WIDE_OPTION UNALIGNED *
  142. AppendMadcapAddressList(
  143. WIDE_OPTION UNALIGNED * Option,
  144. DWORD UNALIGNED *AddrList,
  145. WORD AddrCount,
  146. LPBYTE OptionEnd
  147. )
  148. /*++
  149. Routine Description:
  150. This function appends madcap address list option.
  151. Arguments:
  152. Option - A pointer to a message buffer.
  153. AddrList - The list of the addresses to be attached.
  154. AddrCount - Count of addresses in above list.
  155. OptionEnd - End of Option Buffer.
  156. Return Value:
  157. A pointer to the end of the appended option.
  158. --*/
  159. {
  160. DWORD StartAddr;
  161. WORD i;
  162. WORD BlockCount,BlockSize;
  163. PBYTE Buff;
  164. WORD OptionLength;
  165. if (AddrCount < 1) {
  166. return Option;
  167. }
  168. // First find out how many blocks do we need
  169. for (BlockCount = i = 1; i<AddrCount; i++ ) {
  170. if (ntohl(AddrList[i]) != ntohl(AddrList[i-1]) + 1 ) {
  171. BlockCount++;
  172. }
  173. }
  174. OptionLength = BlockCount*6;
  175. if(((LPBYTE)&Option->OptionValue + OptionLength) >= (OptionEnd - FIELD_OFFSET(WIDE_OPTION, OptionValue)) ) {
  176. DhcpPrint(( 0, "AppendMadcapAddressList failed to append Option "
  177. "Buffer too small\n" ));
  178. return Option;
  179. }
  180. StartAddr = AddrList[0];
  181. BlockSize = 1;
  182. Buff = Option->OptionValue;
  183. for (i = 1; i<AddrCount; i++ ) {
  184. if (ntohl(AddrList[i]) != ntohl(AddrList[i-1]) + 1 ) {
  185. BlockCount--;
  186. *(DWORD UNALIGNED *)Buff = StartAddr;
  187. Buff += 4;
  188. *(WORD UNALIGNED *)Buff = htons(BlockSize);
  189. Buff += 2;
  190. BlockSize = 1;
  191. StartAddr = AddrList[i];
  192. } else {
  193. BlockSize++;
  194. }
  195. }
  196. BlockCount--;
  197. DhcpAssert(0==BlockCount);
  198. *(DWORD UNALIGNED *)Buff = StartAddr;
  199. Buff += 4;
  200. *(WORD UNALIGNED *)Buff = htons(BlockSize);
  201. Buff += 2;
  202. Option->OptionType = ntohs(MADCAP_OPTION_ADDR_LIST);
  203. Option->OptionLength = htons(OptionLength);
  204. Option = (WIDE_OPTION UNALIGNED *)Buff;
  205. DhcpAssert((LPBYTE)Option < OptionEnd);
  206. return Option;
  207. }
  208. DWORD
  209. ExpandMadcapAddressList(
  210. PBYTE AddrRangeList,
  211. WORD AddrRangeListSize,
  212. DWORD UNALIGNED *ExpandList,
  213. WORD *ExpandListSize
  214. )
  215. /*++
  216. Routine Description:
  217. This function expands AddrRangeList from the wire format to array of
  218. addresses.
  219. Arguments:
  220. AddrRangeList - pointer to the AddrRangeList option Buffer.
  221. AddrRangeListSize - size of the above buffer.
  222. ExpandList - the pointer to the array where addresses are to be expanded.
  223. pass NULL if you want to determine the size of the expanded list.
  224. ExpandListSize - No. of elements in above array.
  225. Return Value:
  226. Win32 ErrorCode
  227. --*/
  228. {
  229. WORD TotalCount, BlockSize;
  230. PBYTE ListEnd, Buff;
  231. DWORD StartAddr;
  232. // first count how many addresses we have in the list
  233. ListEnd = AddrRangeList + AddrRangeListSize;
  234. Buff = AddrRangeList;
  235. TotalCount = 0;
  236. while ((Buff + 6 ) <= ListEnd) {
  237. StartAddr = *(DWORD UNALIGNED *) Buff;
  238. Buff += 4;
  239. BlockSize = ntohs(*(WORD UNALIGNED *)Buff);
  240. Buff += 2;
  241. if (!CLASSD_NET_ADDR(StartAddr) || !CLASSD_NET_ADDR(htonl(ntohl(StartAddr)+BlockSize-1)) ) {
  242. return ERROR_BAD_FORMAT;
  243. }
  244. TotalCount += BlockSize;
  245. }
  246. if (NULL == ExpandList) {
  247. *ExpandListSize = TotalCount;
  248. return ERROR_BUFFER_OVERFLOW;
  249. }
  250. if (Buff != ListEnd || TotalCount > *ExpandListSize || 0 == TotalCount) {
  251. return ERROR_BAD_FORMAT;
  252. }
  253. // now expand the actual list.
  254. ListEnd = AddrRangeList + AddrRangeListSize;
  255. Buff = AddrRangeList;
  256. while ((Buff + 6 ) <= ListEnd) {
  257. StartAddr = *(DWORD UNALIGNED *) Buff;
  258. Buff += 4;
  259. BlockSize = ntohs(*(WORD UNALIGNED *)Buff);
  260. Buff += 2;
  261. StartAddr = ntohl(StartAddr);
  262. while (BlockSize--) {
  263. *ExpandList = htonl(StartAddr);
  264. StartAddr++;
  265. ExpandList++;
  266. }
  267. }
  268. DhcpAssert(Buff == ListEnd);
  269. *ExpandListSize = TotalCount;
  270. return ERROR_SUCCESS;
  271. }
  272. LPOPTION
  273. DhcpAppendClientIDOption(
  274. LPOPTION Option,
  275. BYTE ClientHWType,
  276. LPBYTE ClientHWAddr,
  277. BYTE ClientHWAddrLength,
  278. LPBYTE OptionEnd
  279. )
  280. /*++
  281. Routine Description:
  282. This routine appends client ID option to a DHCP message.
  283. History:
  284. 8/26/96 Frankbee Removed 16 byte limitation on the hardware
  285. address
  286. Arguments:
  287. Option - A pointer to the place to append the option request.
  288. ClientHWType - Client hardware type.
  289. ClientHWAddr - Client hardware address
  290. ClientHWAddrLength - Client hardware address length.
  291. OptionEnd - End of Option buffer.
  292. Return Value:
  293. A pointer to the end of the newly appended option.
  294. Note : The client ID option will look like as below in the message:
  295. -----------------------------------------------------------------
  296. | OpNum | Len | HWType | HWA1 | HWA2 | ..... | HWAn |
  297. -----------------------------------------------------------------
  298. --*/
  299. {
  300. struct _CLIENT_ID {
  301. BYTE bHardwareAddressType;
  302. BYTE pbHardwareAddress[0];
  303. } *pClientID;
  304. LPOPTION lpNewOption;
  305. pClientID = DhcpAllocateMemory( sizeof( struct _CLIENT_ID ) + ClientHWAddrLength );
  306. //
  307. // currently there is no way to indicate failure. simply return unmodified option
  308. // list
  309. //
  310. if ( !pClientID )
  311. return Option;
  312. pClientID->bHardwareAddressType = ClientHWType;
  313. memcpy( pClientID->pbHardwareAddress, ClientHWAddr, ClientHWAddrLength );
  314. lpNewOption = DhcpAppendOption(
  315. Option,
  316. OPTION_CLIENT_ID,
  317. (LPBYTE)pClientID,
  318. (BYTE)(ClientHWAddrLength + sizeof(BYTE)),
  319. OptionEnd );
  320. DhcpFreeMemory( pClientID );
  321. return lpNewOption;
  322. }
  323. LPBYTE
  324. DhcpAppendMagicCookie(
  325. LPBYTE Option,
  326. LPBYTE OptionEnd
  327. )
  328. /*++
  329. Routine Description:
  330. This routine appends magic cookie to a DHCP message.
  331. Arguments:
  332. Option - A pointer to the place to append the magic cookie.
  333. OptionEnd - End of Option buffer.
  334. Return Value:
  335. A pointer to the end of the appended cookie.
  336. Note : The magic cookie is :
  337. --------------------
  338. | 99 | 130 | 83 | 99 |
  339. --------------------
  340. --*/
  341. {
  342. DhcpAssert( (Option + 4) < (OptionEnd - 1) );
  343. if( (Option + 4) < (OptionEnd - 1) ) {
  344. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE1;
  345. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE2;
  346. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE3;
  347. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE4;
  348. }
  349. return( Option );
  350. }
  351. LPOPTION
  352. DhcpAppendEnterpriseName(
  353. LPOPTION Option,
  354. PCHAR DSEnterpriseName,
  355. LPBYTE OptionEnd
  356. )
  357. /*++
  358. Routine Description:
  359. This routine appends the name of the enterprise as a MSFT-option to the
  360. DHCP message.
  361. Arguments:
  362. Option - A pointer to the place to append the magic cookie.
  363. DSEnterpriseName - null-terminated string containing name of enterprise
  364. OptionEnd - End of Option buffer.
  365. Return Value:
  366. A pointer to the end of the appended cookie.
  367. --*/
  368. {
  369. CHAR Buffer[260]; // enough room? should we malloc?
  370. DWORD DSEnpriNameLen;
  371. LPOPTION RetOpt;
  372. Buffer[0] = OPTION_MSFT_DSDOMAINNAME_RESP;
  373. if (DSEnterpriseName)
  374. {
  375. // how big is the enterprise name? (include the null terminator)
  376. DSEnpriNameLen = strlen(DSEnterpriseName) + 1;
  377. Buffer[1] = (BYTE)DSEnpriNameLen;
  378. strcpy(&Buffer[2],DSEnterpriseName);
  379. }
  380. //
  381. // if we are not part of any enterprise then DSEnterpriseName will be NULL
  382. // In that case, just return a null-string, so the receiver can positively
  383. // say we are a standalone server (as opposed to ignoring the option)
  384. //
  385. else
  386. {
  387. DSEnpriNameLen = 1;
  388. Buffer[1] = 1;
  389. Buffer[2] = '\0';
  390. }
  391. RetOpt = DhcpAppendOption(
  392. Option,
  393. OPTION_VENDOR_SPEC_INFO,
  394. Buffer,
  395. (BYTE)(DSEnpriNameLen + 2), // include Buffer[0] and Buffer[1]
  396. OptionEnd );
  397. return(RetOpt);
  398. }