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.

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