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.

555 lines
14 KiB

  1. /*
  2. Copyright (c) 1997, Microsoft Corporation, all rights reserved
  3. Description:
  4. Remote Access PPP Bandwidth Allocation Control Protocol core routines
  5. History:
  6. Mar 24, 1997: Vijay Baliga created original version.
  7. */
  8. #include <nt.h> // Required by windows.h
  9. #include <ntrtl.h> // Required by windows.h
  10. #include <nturtl.h> // Required by windows.h
  11. #include <windows.h> // Win32 base API's
  12. #include <rasman.h> // Required by pppcp.h
  13. #include <pppcp.h> // For PPP_CONFIG, PPP_BACP_PROTOCOL, etc
  14. #define INCL_HOSTWIRE
  15. #include <ppputil.h> // For HostToWireFormat16(), etc
  16. #include <stdlib.h> // For rand(), etc
  17. #include <rtutils.h> // For TraceRegister(), etc
  18. #include <raserror.h> // For ERROR_PPP_INVALID_PACKET, etc
  19. #include <rasbacp.h>
  20. DWORD DwBacpTraceId;
  21. /*
  22. Returns:
  23. VOID
  24. Description:
  25. Used for tracing.
  26. */
  27. VOID
  28. TraceBacp(
  29. CHAR * Format,
  30. ...
  31. )
  32. {
  33. va_list arglist;
  34. va_start(arglist, Format);
  35. TraceVprintfEx(DwBacpTraceId,
  36. 0x00010000 | TRACE_USE_MASK |
  37. TRACE_USE_MSEC | TRACE_USE_DATE,
  38. Format,
  39. arglist);
  40. va_end(arglist);
  41. }
  42. /*
  43. Returns:
  44. A random number
  45. Description:
  46. Returns a 4 octet random number that can be used as a magic number.
  47. */
  48. DWORD
  49. CreateMagicNumber(
  50. VOID
  51. )
  52. {
  53. srand(GetCurrentTime());
  54. return(rand());
  55. }
  56. /*
  57. Returns:
  58. NO_ERROR: Success
  59. non-zero error: Failure
  60. Description:
  61. Called to initialize/uninitialize this CP. In the former case, fInitialize
  62. will be TRUE; in the latter case, it will be FALSE.
  63. */
  64. DWORD
  65. BacpInit(
  66. IN BOOL fInitialize
  67. )
  68. {
  69. static BOOL fInitialized = FALSE;
  70. if (fInitialize && !fInitialized)
  71. {
  72. fInitialized = TRUE;
  73. DwBacpTraceId = TraceRegister("RASBACP");
  74. TraceBacp("RasBacpDllMain: DLL_PROCESS_ATTACH");
  75. }
  76. else if (!fInitialize && fInitialized)
  77. {
  78. fInitialized = FALSE;
  79. TraceBacp("RasBacpDllMain: DLL_PROCESS_DETACH");
  80. TraceDeregister(DwBacpTraceId);
  81. }
  82. return(NO_ERROR);
  83. }
  84. /*
  85. Returns:
  86. NO_ERROR: Success
  87. non-zero error: Failure
  88. Description:
  89. This entry point is called once before any other call to BACP is made.
  90. Allocate a work buffer and initialize it.
  91. */
  92. DWORD
  93. BacpBegin(
  94. IN OUT VOID** ppWorkBuf,
  95. IN VOID* pInfo
  96. )
  97. {
  98. DWORD dwError;
  99. TraceBacp("BacpBegin");
  100. *ppWorkBuf = LocalAlloc(LPTR, sizeof(BACPCB));
  101. if (*ppWorkBuf == NULL)
  102. {
  103. dwError = GetLastError();
  104. TraceBacp("BacpBegin: ppWorkBuf is NULL. Error: %d", dwError);
  105. return(dwError);
  106. }
  107. return(NO_ERROR);
  108. }
  109. /*
  110. Returns:
  111. NO_ERROR: Success
  112. Description:
  113. This entry point frees the BACP work buffer.
  114. */
  115. DWORD
  116. BacpEnd(
  117. IN VOID * pWorkBuf
  118. )
  119. {
  120. TraceBacp("BacpEnd");
  121. if (pWorkBuf != NULL)
  122. {
  123. LocalFree(pWorkBuf);
  124. }
  125. return( NO_ERROR );
  126. }
  127. /*
  128. Returns:
  129. NO_ERROR: Success
  130. Description:
  131. This entry point is called to reset the state of BACP. Will re-initialize
  132. the work buffer.
  133. */
  134. DWORD
  135. BacpReset(
  136. IN VOID * pWorkBuf
  137. )
  138. {
  139. BACPCB * pBacpCb = (BACPCB *)pWorkBuf;
  140. TraceBacp("BacpReset");
  141. pBacpCb->dwLocalMagicNumber = CreateMagicNumber();
  142. pBacpCb->dwRemoteMagicNumber = 0;
  143. TraceBacp("BacpReset: Local Magic-Number: %d", pBacpCb->dwLocalMagicNumber);
  144. return(NO_ERROR);
  145. }
  146. /*
  147. Returns:
  148. NO_ERROR: Success
  149. Description:
  150. This entry point is called when BACP is entering Open state.
  151. */
  152. DWORD
  153. BacpThisLayerUp(
  154. IN VOID* pWorkBuf
  155. )
  156. {
  157. BACPCB * pBacpCb = (BACPCB *)pWorkBuf;
  158. TraceBacp("BacpThisLayerUp: Local Magic-Number: %d, "
  159. "Remote Magic-Number: %d",
  160. pBacpCb->dwLocalMagicNumber,
  161. pBacpCb->dwRemoteMagicNumber);
  162. return(NO_ERROR);
  163. }
  164. /*
  165. Returns:
  166. NO_ERROR: Success
  167. ERROR_BUFFER_TOO_SMALL: pSendConfig is too small
  168. Description:
  169. This entry point is called to make a confifure request packet.
  170. */
  171. DWORD
  172. BacpMakeConfigRequest(
  173. IN VOID * pWorkBuffer,
  174. IN PPP_CONFIG * pSendConfig,
  175. IN DWORD cbSendConfig
  176. )
  177. {
  178. BACPCB * pBacpCb = (BACPCB*)pWorkBuffer;
  179. PPP_OPTION * pPppOption = (PPP_OPTION *)pSendConfig->Data;
  180. TraceBacp("BacpMakeConfigRequest");
  181. if (cbSendConfig < PPP_CONFIG_HDR_LEN + PPP_OPTION_HDR_LEN + 4)
  182. {
  183. TraceBacp("BacpMakeConfigRequest: Buffer is too small. Size: %d",
  184. cbSendConfig);
  185. return(ERROR_BUFFER_TOO_SMALL);
  186. }
  187. pSendConfig->Code = CONFIG_REQ;
  188. HostToWireFormat16((WORD)(PPP_CONFIG_HDR_LEN + PPP_OPTION_HDR_LEN + 4),
  189. pSendConfig->Length);
  190. pPppOption->Type = BACP_OPTION_FAVORED_PEER;
  191. pPppOption->Length = PPP_OPTION_HDR_LEN + 4;
  192. HostToWireFormat32(pBacpCb->dwLocalMagicNumber, pPppOption->Data);
  193. return(NO_ERROR);
  194. }
  195. /*
  196. Returns:
  197. NO_ERROR: Success
  198. ERROR_PPP_INVALID_PACKET: Length of option is wrong
  199. Description:
  200. This entry point is called when a configure request packet is received.
  201. */
  202. DWORD
  203. BacpMakeConfigResult(
  204. IN VOID * pWorkBuffer,
  205. IN PPP_CONFIG * pRecvConfig,
  206. OUT PPP_CONFIG * pSendConfig,
  207. IN DWORD cbSendConfig,
  208. IN BOOL fRejectNaks
  209. )
  210. {
  211. BACPCB * pBacpCb = (BACPCB*)pWorkBuffer;
  212. PPP_OPTION * pSendOption = (PPP_OPTION *)(pSendConfig->Data);
  213. PPP_OPTION * pRecvOption = (PPP_OPTION *)(pRecvConfig->Data);
  214. LONG lSendLength = cbSendConfig - PPP_CONFIG_HDR_LEN;
  215. LONG lRecvLength = WireToHostFormat16(pRecvConfig->Length)
  216. - PPP_CONFIG_HDR_LEN;
  217. DWORD dwResultType = CONFIG_ACK;
  218. DWORD dwResult;
  219. TraceBacp("BacpMakeConfigResult");
  220. while(lRecvLength > 0)
  221. {
  222. if (pRecvOption->Length == 0)
  223. {
  224. TraceBacp("BacpMakeConfigResult: Invalid option. Length is 0");
  225. return(ERROR_PPP_INVALID_PACKET);
  226. }
  227. if ((lRecvLength -= pRecvOption->Length) < 0)
  228. {
  229. TraceBacp("BacpMakeConfigResult: Invalid option. Length: %d",
  230. pRecvOption->Length);
  231. return(ERROR_PPP_INVALID_PACKET);
  232. }
  233. // We only know BACP_OPTION_FAVORED_PEER
  234. if ((pRecvOption->Length != PPP_OPTION_HDR_LEN + 4) ||
  235. (pRecvOption->Type != BACP_OPTION_FAVORED_PEER))
  236. {
  237. TraceBacp("BacpMakeConfigResult: Unknown option. "
  238. "Type: %d, Length: %d",
  239. pRecvOption->Type, pRecvOption->Length);
  240. dwResult = CONFIG_REJ;
  241. }
  242. else
  243. {
  244. pBacpCb->dwRemoteMagicNumber =
  245. WireToHostFormat32(pRecvOption->Data);
  246. // A Magic-Number of zero is illegal and MUST always be Nak'd.
  247. if ((pBacpCb->dwRemoteMagicNumber == 0) ||
  248. (pBacpCb->dwRemoteMagicNumber == pBacpCb->dwLocalMagicNumber))
  249. {
  250. TraceBacp("BacpMakeConfigResult: Unacceptable Magic-Number: %d",
  251. pBacpCb->dwRemoteMagicNumber);
  252. pBacpCb->dwRemoteMagicNumber = CreateMagicNumber();
  253. TraceBacp("BacpMakeConfigResult: Suggesting new "
  254. "Magic-Number: %d",
  255. pBacpCb->dwRemoteMagicNumber);
  256. dwResult = CONFIG_NAK;
  257. }
  258. else
  259. {
  260. dwResult = CONFIG_ACK;
  261. }
  262. }
  263. /*
  264. If we were building an ACK and we got a NAK or reject OR we were
  265. building a NAK and we got a reject.
  266. */
  267. if ( ((dwResultType == CONFIG_ACK) && (dwResult != CONFIG_ACK)) ||
  268. ((dwResultType == CONFIG_NAK) && (dwResult == CONFIG_REJ)))
  269. {
  270. dwResultType = dwResult;
  271. pSendOption = (PPP_OPTION *)(pSendConfig->Data);
  272. lSendLength = cbSendConfig - PPP_CONFIG_HDR_LEN;
  273. }
  274. // Add the option to the list.
  275. if (dwResult == dwResultType)
  276. {
  277. /*
  278. If this option is to be rejected, simply copy the rejected option
  279. to the send buffer.
  280. */
  281. if ((dwResult == CONFIG_REJ) ||
  282. ((dwResult == CONFIG_NAK) && (fRejectNaks)))
  283. {
  284. CopyMemory(pSendOption, pRecvOption, pRecvOption->Length);
  285. }
  286. else
  287. {
  288. pSendOption->Type = BACP_OPTION_FAVORED_PEER;
  289. pSendOption->Length = PPP_OPTION_HDR_LEN + 4;
  290. HostToWireFormat32(pBacpCb->dwRemoteMagicNumber,
  291. pSendOption->Data);
  292. }
  293. lSendLength -= pSendOption->Length;
  294. pSendOption = (PPP_OPTION *)
  295. ((BYTE *)pSendOption + pSendOption->Length);
  296. }
  297. pRecvOption = (PPP_OPTION *)((BYTE*)pRecvOption + pRecvOption->Length);
  298. }
  299. /*
  300. If this was an NAK and we have cannot send any more NAKS then we make this
  301. a REJECT packet.
  302. */
  303. if ((dwResultType == CONFIG_NAK) && fRejectNaks)
  304. pSendConfig->Code = CONFIG_REJ;
  305. else
  306. pSendConfig->Code = (BYTE)dwResultType;
  307. TraceBacp("BacpMakeConfigResult: Sending %s",
  308. pSendConfig->Code == CONFIG_ACK ? "ACK" :
  309. (pSendConfig->Code == CONFIG_NAK ? "NAK" : "REJ"));
  310. HostToWireFormat16((WORD)(cbSendConfig - lSendLength), pSendConfig->Length);
  311. return(NO_ERROR);
  312. }
  313. /*
  314. Returns:
  315. NO_ERROR: Success
  316. ERROR_PPP_INVALID_PACKET: This is not the packet we sent
  317. Description:
  318. This entry point is called when a configure ack or configure rej packet is
  319. received.
  320. */
  321. DWORD
  322. BacpConfigAckOrRejReceived(
  323. IN VOID * pWorkBuffer,
  324. IN PPP_CONFIG * pRecvConfig
  325. )
  326. {
  327. BACPCB * pBacpCb = (BACPCB *)pWorkBuffer;
  328. PPP_OPTION * pRecvOption = (PPP_OPTION *)(pRecvConfig->Data);
  329. DWORD dwLength = WireToHostFormat16(pRecvConfig->Length);
  330. DWORD dwMagicNumber = WireToHostFormat32(pRecvOption->Data);
  331. TraceBacp("BacpConfigAckOrRejReceived");
  332. if ((dwLength != PPP_CONFIG_HDR_LEN + PPP_OPTION_HDR_LEN + 4) ||
  333. (pRecvOption->Type != BACP_OPTION_FAVORED_PEER) ||
  334. (pRecvOption->Length != PPP_OPTION_HDR_LEN + 4) ||
  335. (dwMagicNumber != pBacpCb->dwLocalMagicNumber))
  336. {
  337. TraceBacp("BacpConfigAckOrRejReceived: Invalid packet received");
  338. return(ERROR_PPP_INVALID_PACKET);
  339. }
  340. else
  341. return(NO_ERROR);
  342. }
  343. /*
  344. Returns:
  345. NO_ERROR: Success
  346. ERROR_PPP_INVALID_PACKET: Length of option is wrong
  347. Description:
  348. This entry point is called when a configure nak packet is received.
  349. */
  350. DWORD
  351. BacpConfigNakReceived(
  352. IN VOID * pWorkBuffer,
  353. IN PPP_CONFIG * pRecvConfig
  354. )
  355. {
  356. BACPCB * pBacpCb = (BACPCB *)pWorkBuffer;
  357. PPP_OPTION * pOption = (PPP_OPTION*)(pRecvConfig->Data);
  358. LONG lRecvLength = WireToHostFormat16(pRecvConfig->Length)
  359. - PPP_CONFIG_HDR_LEN;
  360. TraceBacp("BacpConfigNakReceived");
  361. while (lRecvLength > 0)
  362. {
  363. if (pOption->Length == 0)
  364. {
  365. TraceBacp("BacpConfigNakReceived: Invalid option. Length is 0");
  366. return(ERROR_PPP_INVALID_PACKET);
  367. }
  368. if ((lRecvLength -= pOption->Length) < 0)
  369. {
  370. TraceBacp("BacpConfigNakReceived: Invalid option. Length: %d",
  371. pOption->Length);
  372. return(ERROR_PPP_INVALID_PACKET);
  373. }
  374. if ((pOption->Type == BACP_OPTION_FAVORED_PEER) &&
  375. (pOption->Length == PPP_OPTION_HDR_LEN + 4))
  376. {
  377. pBacpCb->dwLocalMagicNumber = WireToHostFormat32(pOption->Data);
  378. TraceBacp("BacpConfigNakReceived: New Local Magic-Number: %d",
  379. pBacpCb->dwLocalMagicNumber);
  380. }
  381. pOption = (PPP_OPTION *)((BYTE *)pOption + pOption->Length);
  382. }
  383. return(NO_ERROR);
  384. }
  385. /*
  386. Returns:
  387. NO_ERROR: Success
  388. ERROR_INVALID_PARAMETER: Protocol id is unrecogized
  389. Description:
  390. This entry point is called to get all information for the control protocol
  391. in this module.
  392. */
  393. DWORD
  394. BacpGetInfo(
  395. IN DWORD dwProtocolId,
  396. OUT PPPCP_INFO* pCpInfo
  397. )
  398. {
  399. if (dwProtocolId != PPP_BACP_PROTOCOL)
  400. return(ERROR_INVALID_PARAMETER);
  401. ZeroMemory(pCpInfo, sizeof(PPPCP_INFO));
  402. pCpInfo->Protocol = PPP_BACP_PROTOCOL;
  403. lstrcpy(pCpInfo->SzProtocolName, "BACP");
  404. pCpInfo->Recognize = PROT_REJ;
  405. pCpInfo->RasCpInit = BacpInit;
  406. pCpInfo->RasCpBegin = BacpBegin;
  407. pCpInfo->RasCpEnd = BacpEnd;
  408. pCpInfo->RasCpReset = BacpReset;
  409. pCpInfo->RasCpThisLayerUp = BacpThisLayerUp;
  410. pCpInfo->RasCpMakeConfigRequest = BacpMakeConfigRequest;
  411. pCpInfo->RasCpMakeConfigResult = BacpMakeConfigResult;
  412. pCpInfo->RasCpConfigAckReceived = BacpConfigAckOrRejReceived;
  413. pCpInfo->RasCpConfigNakReceived = BacpConfigNakReceived;
  414. pCpInfo->RasCpConfigRejReceived = BacpConfigAckOrRejReceived;
  415. return(NO_ERROR);
  416. }