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.

4890 lines
138 KiB

  1. /*
  2. Copyright (c) 1997, Microsoft Corporation, all rights reserved
  3. Description:
  4. Remote Access PPP Bandwidth Allocation Protocol routines. Based on
  5. RFC 2125.
  6. History:
  7. Mar 27, 1997: Vijay Baliga created original version.
  8. Overview:
  9. When NdisWan tells us that a link has to be added or dropped,
  10. BapEventAddLink or BapEventDropLink gets called. They call FFillBapCb to
  11. fill in the BAPCB structure of the bundle. The BAPCB structure is mostly
  12. used for holding values of the various BAP Datagram Options. FFillBapCb
  13. calls FGetAvailableLink[ClientOrRouter | NonRouterServer] to see if links
  14. are available, and if so, to choose one. If FFillBapCb returns FALSE, then
  15. we cannot satisfy NdisWan's request. Otherwise, we call
  16. FSendInitialBapRequest to send the request to the peer.
  17. When we get a packet from the peer, BapEventReceive gets called. It calls
  18. the various BapEventRecv* functions, eg BapEventRecvCallOrCallbackReq,
  19. BapEventRecvDropResp, etc. We respond by calling FSendBapResponse.
  20. Before we send a Callback-Request, or ACK a Call-Request, we call
  21. FListenForCall if we are a non-router client. Routers and servers are
  22. always listening anyway, so we don't explicitly start listening.
  23. If our Call-Request is ACK'ed or we ACK a Callback-Request, we call FCall
  24. to add another link to the multilink bundle. Clients and routers call
  25. RasDial. Non-router servers send messages to Ddm.
  26. The bundles are always in one of several BAP_STATEs, eg BAP_STATE_INITIAL
  27. (the rest state), BAP_STATE_CALLING, etc. Call-Requests and
  28. Callback-Requests are NAK'ed unless the state is INITIAL, SENT_CALL_REQ, or
  29. SENT_CALLBACK_REQ (the latter two to resolve race conditions).
  30. Drop-Requests are NAK'ed unless the state is INITIAL or SEND_DROP_REQ (the
  31. latter to resolve race conditions).
  32. Note on Dropping Links:
  33. We want to forcibly drop links when the utilization falls below a cutoff.
  34. The server wants to do this to prevent users from hogging ports. The client
  35. wants to do this to save money on calls.
  36. Before sending a BAP_PACKET_DROP_REQ, we note down the number of active
  37. links (in BapCb.dwLinCount) and set fForceDropOnNak to TRUE. If the packet
  38. times out or we get any response other than ACK, we summarily drop the link
  39. by calling FsmClose if the number of active links has not decreased and
  40. fForceDropOnNak is still TRUE.
  41. fForceDropOnNak is set to FALSE if there is a race condition and we are not
  42. the favored peer. We then mark the link for dropping and insert an item in
  43. the timer queue. After BAP_TIMEOUT_FAV_PEER sec, if the peer has still not
  44. dropped the link, and we have at least two active links, we summarily drop
  45. the link by calling FsmClose.
  46. Note on the "previously known number" for calculating Phone-Deltas:
  47. 1) Client sending its numbers to the server (425 882 5759 and 425 882 5760)
  48. Client sends 011 91 425 882 5759. Server dials it.
  49. Client sends 011 91 425 882 5760. Server applies delta to above number.
  50. 2) Server sending its numbers to the client. Client called 882 5759 first.
  51. (425 882 5759, 425 882 5660, 425 882 5758, 425 882 6666)
  52. Server sends 660. Client applies delta to first number.
  53. Server sends 758 (not just 8). Client applies delta to first number.
  54. Server sends 6666. Client applies delta to first number.
  55. This works irrespective of whether the 3rd party client applies delta to
  56. the first number or the last number.
  57. If the client gets 011 91 425 882 5660, it must just dial the last 7
  58. digits, since it dialed only 7 digits the first time.
  59. */
  60. #include <nt.h> // Required by windows.h
  61. #include <ntrtl.h> // Required by windows.h
  62. #include <nturtl.h> // Required by windows.h
  63. #include <windows.h> // Win32 base API's
  64. #include <raserror.h> // For ERROR_BUFFER_TOO_SMALL, etc
  65. #include <mprerror.h> // For ERROR_BAP_DISCONNECTED, etc
  66. #include <mprlog.h> // For ROUTERLOG_BAP_DISCONNECTED, etc
  67. #include <rasman.h> // Required by pppcp.h
  68. #include <pppcp.h> // For PPP_CONFIG_HDR_LEN, PPP_BACP_PROTOCOL, etc
  69. #include <ppp.h> // For PCB, PPP_PACKET, etc. Reqd by bap.h
  70. #include <rtutils.h> // For RTASSERT (PPP_ASSERT)
  71. #include <util.h> // For GetCpIndexFromProtocol(), etc
  72. #include <timer.h> // For InsertInTimerQ(), RemoveFromTimerQ()
  73. #include <smevents.h> // For FsmClose()
  74. #include <worker.h> // For ProcessCallResult()
  75. #include <bap.h>
  76. #include <rasbacp.h> // For BACPCB
  77. #define BAP_KEY_CLIENT_CALLBACK "Software\\Microsoft\\RAS Phonebook\\Callback"
  78. #define BAP_KEY_SERVER_CALLBACK "Software\\Microsoft\\Router Phonebook\\Callback"
  79. #define BAP_VAL_NUMBER "Number"
  80. /*
  81. Description:
  82. g_dwMandatoryOptions[BAP_PACKET_foo] contains the mandatory options for BAP
  83. Datagram BAP_PACKET_foo.
  84. */
  85. static DWORD g_dwMandatoryOptions[] =
  86. {
  87. 0,
  88. BAP_N_LINK_TYPE,
  89. 0,
  90. BAP_N_LINK_TYPE | BAP_N_PHONE_DELTA,
  91. 0,
  92. BAP_N_LINK_DISC,
  93. 0,
  94. BAP_N_CALL_STATUS,
  95. 0
  96. };
  97. /*
  98. Returns:
  99. void
  100. Description:
  101. Used for printing BAP trace statements.
  102. */
  103. VOID
  104. BapTrace(
  105. IN CHAR* Format,
  106. ...
  107. )
  108. {
  109. va_list arglist;
  110. va_start(arglist, Format);
  111. TraceVprintfEx(DwBapTraceId,
  112. 0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC,
  113. Format,
  114. arglist);
  115. va_end(arglist);
  116. }
  117. /*
  118. Returns:
  119. TRUE: Success
  120. FALSE: Failure
  121. Description:
  122. Calls RasPortEnum() and returns an array of RASMAN_PORT's in *ppRasmanPort
  123. and the number of elements in the array in *pdwNumPorts. If this function
  124. fails, *ppRasmanPort will be NULL and *pdwNumPorts will be 0. If this
  125. function succeeds, the caller must call LOCAL_FREE(*ppRasmanPort);
  126. */
  127. BOOL
  128. FEnumPorts(
  129. OUT RASMAN_PORT** ppRasmanPort,
  130. OUT DWORD* pdwNumPorts
  131. )
  132. {
  133. DWORD dwErr;
  134. DWORD dwSize;
  135. DWORD dwNumEntries;
  136. BOOL fRet = FALSE;
  137. PPP_ASSERT(NULL != ppRasmanPort);
  138. PPP_ASSERT(NULL != pdwNumPorts);
  139. *ppRasmanPort = NULL;
  140. dwSize = 0;
  141. dwErr = RasPortEnum(NULL, NULL /* buffer */, &dwSize, &dwNumEntries);
  142. PPP_ASSERT(ERROR_BUFFER_TOO_SMALL == dwErr);
  143. *ppRasmanPort = (RASMAN_PORT*) LOCAL_ALLOC(LPTR, dwSize);
  144. if (NULL == *ppRasmanPort)
  145. {
  146. BapTrace("FEnumPorts: Out of memory.");
  147. goto LDone;
  148. }
  149. dwErr = RasPortEnum(NULL, (BYTE*)*ppRasmanPort, &dwSize, &dwNumEntries);
  150. if (NO_ERROR != dwErr)
  151. {
  152. BapTrace("FEnumPorts: RasPortEnum returned error %d", dwErr);
  153. goto LDone;
  154. }
  155. fRet = TRUE;
  156. LDone:
  157. if (!fRet)
  158. {
  159. if (NULL != *ppRasmanPort)
  160. {
  161. LOCAL_FREE(*ppRasmanPort);
  162. }
  163. *ppRasmanPort = NULL;
  164. *pdwNumPorts = 0;
  165. }
  166. *pdwNumPorts = dwNumEntries;
  167. return(fRet);
  168. }
  169. /*
  170. Returns:
  171. TRUE: ASCII digits
  172. FALSE: not ASCII digits
  173. Description:
  174. Looks at dwLength bytes in *pByte. Returns TRUE iff all of them are ASCII
  175. digits.
  176. */
  177. BOOL
  178. FAsciiDigits(
  179. IN BYTE* pByte,
  180. IN DWORD dwLength
  181. )
  182. {
  183. PPP_ASSERT(NULL != pByte);
  184. while (dwLength--)
  185. {
  186. if (!isdigit(pByte[dwLength]))
  187. {
  188. if (FDoBapOnVpn && '.' == pByte[dwLength])
  189. {
  190. continue;
  191. }
  192. else
  193. {
  194. return(FALSE);
  195. }
  196. }
  197. }
  198. return(TRUE);
  199. }
  200. /*
  201. Returns:
  202. TRUE: Success
  203. FALSE: Failure
  204. Description:
  205. Given a pointer to a RASMAN_PORT, this function returns the link type (in
  206. *pdwLinkType) and link speed in kbps (in *pdwLinkSpeed) for the associated
  207. port. The link type is the same as the Link Type in the Link-Type BAP
  208. option: 1 for ISDN, 2 for X.25, and 4 for modem. If this function fails,
  209. *pdwLinkType and *pdwLinkSpeed will be set to 0.
  210. */
  211. BOOL
  212. FGetLinkTypeAndSpeedFromRasmanPort(
  213. IN RASMAN_PORT* pRasmanPort,
  214. OUT DWORD* pdwLinkType,
  215. OUT DWORD* pdwLinkSpeed
  216. )
  217. {
  218. BOOL fRet = TRUE;
  219. PPP_ASSERT(NULL != pRasmanPort);
  220. PPP_ASSERT(NULL != pdwLinkType);
  221. PPP_ASSERT(NULL != pdwLinkSpeed);
  222. if (!lstrcmpi(pRasmanPort->P_DeviceType, RASDT_Isdn))
  223. {
  224. *pdwLinkType = 1;
  225. *pdwLinkSpeed = 64;
  226. }
  227. else if (!lstrcmpi(pRasmanPort->P_DeviceType, RASDT_X25))
  228. {
  229. *pdwLinkType = 2;
  230. *pdwLinkSpeed = 56;
  231. }
  232. else if (!lstrcmpi(pRasmanPort->P_DeviceType, RASDT_Modem))
  233. {
  234. *pdwLinkType = 4;
  235. *pdwLinkSpeed = 56;
  236. }
  237. else if (FDoBapOnVpn && !lstrcmpi(pRasmanPort->P_DeviceType, RASDT_Vpn))
  238. {
  239. *pdwLinkType = 32;
  240. *pdwLinkSpeed = 10000;
  241. }
  242. else
  243. {
  244. // BapTrace("Unknown LinkType %s", pRasmanPort->P_DeviceType);
  245. *pdwLinkType = 0;
  246. *pdwLinkSpeed = 0;
  247. fRet = FALSE;
  248. }
  249. return(fRet);
  250. }
  251. /*
  252. Returns:
  253. TRUE: Success
  254. FALSE: Failure
  255. Description:
  256. Given an hPort, this function tries to find out the phone number that the
  257. peer can dial to connect to the device that the port belongs to. The phone
  258. number (only ASCII digits, and with at most RAS_MaxCallbackNumber chars) is
  259. returned in szOurPhoneNumber.
  260. */
  261. BOOL
  262. FGetOurPhoneNumberFromHPort(
  263. IN HPORT hPort,
  264. OUT CHAR* szOurPhoneNumber
  265. )
  266. {
  267. BOOL fRet = FALSE;
  268. RAS_CONNECT_INFO* pRasConnectInfo = NULL;
  269. DWORD dwSize;
  270. DWORD dwErr;
  271. ZeroMemory(szOurPhoneNumber, (RAS_MaxCallbackNumber + 1) * sizeof(CHAR));
  272. dwSize = 0;
  273. dwErr = RasGetConnectInfo(hPort, &dwSize, NULL);
  274. if (ERROR_BUFFER_TOO_SMALL != dwErr)
  275. {
  276. BapTrace("RasGetConnectInfo failed and returned 0x%x", dwErr);
  277. goto LDone;
  278. }
  279. pRasConnectInfo = (RAS_CONNECT_INFO*) LOCAL_ALLOC(LPTR, dwSize);
  280. if (NULL == pRasConnectInfo)
  281. {
  282. BapTrace("FGetOurPhoneNumbersFromHPort: Out of memory.");
  283. goto LDone;
  284. }
  285. dwErr = RasGetConnectInfo(hPort, &dwSize, pRasConnectInfo);
  286. if (NO_ERROR != dwErr)
  287. {
  288. BapTrace("RasGetConnectInfo failed and returned 0x%x", dwErr);
  289. goto LDone;
  290. }
  291. if ( (0 < pRasConnectInfo->dwCalledIdSize)
  292. && (0 != pRasConnectInfo->pszCalledId[0]))
  293. {
  294. strncpy(szOurPhoneNumber, pRasConnectInfo->pszCalledId,
  295. RAS_MaxCallbackNumber);
  296. }
  297. else if ( (0 < pRasConnectInfo->dwAltCalledIdSize)
  298. && (0 != pRasConnectInfo->pszAltCalledId[0]))
  299. {
  300. strncpy(szOurPhoneNumber, pRasConnectInfo->pszAltCalledId,
  301. RAS_MaxCallbackNumber);
  302. }
  303. fRet = TRUE;
  304. LDone:
  305. if (NULL != pRasConnectInfo)
  306. {
  307. LOCAL_FREE(pRasConnectInfo);
  308. }
  309. return(fRet);
  310. }
  311. /*
  312. Returns:
  313. TRUE: Success
  314. FALSE: Failure
  315. Description:
  316. Given a port name, szPortName, this function tries to find out the phone
  317. number that the peer has to dial to connect to the port. The phone number
  318. is returned in szOurPhoneNumber, whose size must be at least
  319. RAS_MaxCallbackNumber + 1. If we are the server or the router,
  320. fRouterPhoneBook must be TRUE and szTextualSid is ignored. Otherwise,
  321. fRouterPhoneBook must be FALSE and szTextualSid must contain the
  322. textual sid of the logged on user.
  323. */
  324. BOOL
  325. FGetOurPhoneNumberFromPortName(
  326. IN CHAR* szPortName,
  327. OUT CHAR* szOurPhoneNumber,
  328. IN BOOL fRouterPhoneBook,
  329. IN CHAR* szTextualSid
  330. )
  331. {
  332. BOOL fRet = FALSE;
  333. HKEY hKeyCallback;
  334. BOOL fCloseHKeyCallback = FALSE;
  335. HKEY hKey;
  336. DWORD dwIndex;
  337. DWORD dwSize;
  338. FILETIME FileTime;
  339. CHAR szCallbackNumber[RAS_MaxCallbackNumber + 1];
  340. DWORD dwErr;
  341. // The size has been obtained from DeviceAndPortFromPsz in noui.c:
  342. CHAR szDeviceAndPort[RAS_MaxDeviceName + 2 + MAX_PORT_NAME + 1 + 1];
  343. CHAR* pchStart;
  344. CHAR* pchEnd;
  345. CHAR* szCallback;
  346. PPP_ASSERT(NULL != szPortName);
  347. PPP_ASSERT(NULL != szOurPhoneNumber);
  348. if (fRouterPhoneBook)
  349. {
  350. szCallback = BAP_KEY_SERVER_CALLBACK;
  351. }
  352. else
  353. {
  354. szCallback = BAP_KEY_CLIENT_CALLBACK;
  355. }
  356. fCloseHKeyCallback = FALSE;
  357. if (fRouterPhoneBook)
  358. {
  359. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szCallback, 0, KEY_READ,
  360. &hKeyCallback);
  361. if (NO_ERROR != dwErr)
  362. {
  363. BapTrace("RegOpenKeyEx on %s returned error %d", szCallback, dwErr);
  364. goto LDone;
  365. }
  366. }
  367. else
  368. {
  369. if (NULL == szTextualSid)
  370. {
  371. BapTrace("Textual Sid is not known");
  372. goto LDone;
  373. }
  374. dwErr = RegOpenKeyEx(HKEY_USERS, szTextualSid, 0, KEY_READ, &hKey);
  375. if (NO_ERROR != dwErr)
  376. {
  377. BapTrace("RegOpenKeyEx on %s returned error %d", szTextualSid,
  378. dwErr);
  379. goto LDone;
  380. }
  381. dwErr = RegOpenKeyEx(hKey, szCallback, 0, KEY_READ, &hKeyCallback);
  382. RegCloseKey(hKey);
  383. if (NO_ERROR != dwErr)
  384. {
  385. BapTrace("RegOpenKeyEx on %s returned error %d", szCallback, dwErr);
  386. goto LDone;
  387. }
  388. }
  389. fCloseHKeyCallback = TRUE;
  390. dwIndex = 0;
  391. while (TRUE)
  392. {
  393. dwSize = sizeof(szDeviceAndPort);
  394. dwErr = RegEnumKeyEx(hKeyCallback, dwIndex++,
  395. szDeviceAndPort, &dwSize,
  396. NULL, NULL, NULL, &FileTime);
  397. if (ERROR_NO_MORE_ITEMS == dwErr)
  398. {
  399. break;
  400. }
  401. if (ERROR_MORE_DATA == dwErr)
  402. {
  403. BapTrace("The buffer is too small for key %d in %s",
  404. dwIndex, szCallback);
  405. continue;
  406. }
  407. if (NO_ERROR != dwErr)
  408. {
  409. BapTrace("RegEnumKeyEx on %s returned error %d",
  410. szCallback, dwErr);
  411. break;
  412. }
  413. pchEnd = szDeviceAndPort + strlen(szDeviceAndPort) - 1;
  414. pchStart = pchEnd;
  415. while (szDeviceAndPort < pchStart)
  416. {
  417. if ('(' == *pchStart)
  418. {
  419. break;
  420. }
  421. else
  422. {
  423. pchStart -= 1;
  424. }
  425. }
  426. if ( (szDeviceAndPort < pchStart) && (pchStart < pchEnd)
  427. && ('(' == *pchStart) && (')' == *pchEnd))
  428. {
  429. *pchEnd = 0;
  430. pchStart += 1;
  431. }
  432. else
  433. {
  434. BapTrace("Invalid DeviceAndPort %s in key %s",
  435. szDeviceAndPort, szCallback);
  436. continue;
  437. }
  438. if (!lstrcmpi(pchStart, szPortName))
  439. {
  440. *pchEnd = ')';
  441. dwErr = RegOpenKeyEx(hKeyCallback, szDeviceAndPort, 0, KEY_READ,
  442. &hKey);
  443. if (NO_ERROR != dwErr)
  444. {
  445. BapTrace("RegOpenKeyEx on %s returned error %d", szDeviceAndPort,
  446. dwErr);
  447. break;
  448. }
  449. dwSize = RAS_MaxCallbackNumber + 1;
  450. dwErr = RegQueryValueEx(hKey, BAP_VAL_NUMBER, NULL, NULL,
  451. szCallbackNumber, &dwSize);
  452. RegCloseKey(hKey);
  453. if (NO_ERROR != dwErr)
  454. {
  455. BapTrace("RegQueryValueEx on %s\\%s failed. Error: %d",
  456. szDeviceAndPort, BAP_VAL_NUMBER, dwErr);
  457. break;
  458. }
  459. RemoveNonNumerals(szCallbackNumber);
  460. if (szCallbackNumber[0])
  461. {
  462. lstrcpy(szOurPhoneNumber, szCallbackNumber);
  463. fRet = TRUE;
  464. }
  465. break;
  466. }
  467. }
  468. LDone:
  469. if (fCloseHKeyCallback)
  470. {
  471. RegCloseKey(hKeyCallback);
  472. }
  473. if (!fRet)
  474. {
  475. BapTrace("No callback number for port %s", szPortName);
  476. }
  477. return(fRet);
  478. }
  479. /*
  480. Returns:
  481. TRUE: Success
  482. FALSE: Failure
  483. Description:
  484. Writes a Phone-Delta in pbPhoneDelta using szOurPhoneNumber as the phone
  485. number to send to the peer and szBasePhoneNumber as the "previously known
  486. number". If the lengths of the szOurPhoneNumber and szBasePhoneNumber are
  487. different, or if szBasePhoneNumber is NULL, it writes the entire
  488. PhoneNumber into pbPhoneDelta. Otherwise, the unique portion of
  489. szBasePhoneNumber is overwritten with X's so that the unique portion will
  490. never decrease.
  491. *pdwNumBytes contains the number of bytes the function can write in
  492. pbPhoneDelta. On exit, it is decremented by the number of bytes actually
  493. written.
  494. NOTE: NOTE: NOTE: NOTE: NOTE:
  495. If the function returns FALSE, nothing will be written in pbPhoneDelta and
  496. *pdwNumBytes will be left unchanged.
  497. */
  498. BOOL
  499. FWritePhoneDelta(
  500. IN CHAR* szOurPhoneNumber,
  501. IN CHAR* szBasePhoneNumber,
  502. OUT BYTE* pbPhoneDelta,
  503. IN OUT DWORD* pdwNumBytes)
  504. {
  505. DWORD dwNumCharsPhoneNumber;
  506. DWORD dwNumCharsBase = 0;
  507. DWORD dwDeltaIndex;
  508. DWORD dwTemp;
  509. DWORD dwNumCharsUnique;
  510. BOOL fRet = FALSE;
  511. PPP_ASSERT(NULL != szOurPhoneNumber);
  512. PPP_ASSERT(NULL != pbPhoneDelta);
  513. PPP_ASSERT(NULL != pdwNumBytes);
  514. dwNumCharsPhoneNumber = lstrlen(szOurPhoneNumber);
  515. if (0 == dwNumCharsPhoneNumber)
  516. {
  517. BapTrace("szOurPhoneNumbers is an empty string");
  518. goto LDone;
  519. }
  520. if (NULL != szBasePhoneNumber)
  521. {
  522. dwNumCharsBase = lstrlen(szBasePhoneNumber);
  523. }
  524. dwDeltaIndex = 0;
  525. if ((NULL != szBasePhoneNumber) &&
  526. (dwNumCharsPhoneNumber == dwNumCharsBase))
  527. {
  528. // Find the substring of szOurPhoneNumber that differs from
  529. // szBasePhoneNumber.
  530. while ((0 != szOurPhoneNumber[dwDeltaIndex]) &&
  531. (szOurPhoneNumber[dwDeltaIndex] ==
  532. szBasePhoneNumber[dwDeltaIndex]))
  533. {
  534. dwDeltaIndex++;
  535. }
  536. for (dwTemp = dwDeltaIndex; 0 != szBasePhoneNumber[dwTemp];
  537. dwTemp++)
  538. {
  539. // We want to make sure that the Unique portion will increase
  540. // each time, ie if we sent 3 unique digits last time, this time
  541. // we should send atleast 3. This is because we don't know
  542. // whether the peer will apply the phone delta to the first
  543. // number received or the latest one.
  544. szBasePhoneNumber[dwTemp] = 'X';
  545. }
  546. }
  547. // The unique part of szOurPhoneNumber begins at
  548. // szOurPhoneNumber[dwDeltaIndex].
  549. dwNumCharsUnique = dwNumCharsPhoneNumber - dwDeltaIndex;
  550. if (0 == dwNumCharsUnique)
  551. {
  552. // Other implementations may not be able to handle 0 Unique-Digits
  553. dwNumCharsUnique = 1;
  554. dwDeltaIndex -= 1;
  555. }
  556. #if 0
  557. // Do not remove this code. It shows how we would have handled 0
  558. // Unique-Digits.
  559. if (0 == dwNumCharsUnique)
  560. {
  561. // szOurPhoneNumber and szBasePhoneNumber are the same.
  562. if (1 > *pdwNumBytes)
  563. {
  564. BapTrace("No space in pbPhoneDelta");
  565. return(FALSE);
  566. }
  567. // See BAPCB comments for an explanation of the 0xFF weirdness.
  568. pbPhoneDelta[0] = 0xFF;
  569. *pdwNumBytes -= 1;
  570. return(TRUE);
  571. }
  572. #endif
  573. RTASSERT(FAsciiDigits(szOurPhoneNumber + dwDeltaIndex,
  574. dwNumCharsUnique));
  575. // Our phone numbers should have no more than RAS_MaxPhoneNumber (128)
  576. // digits.
  577. PPP_ASSERT(0xFF >= dwNumCharsUnique);
  578. if (dwNumCharsUnique + 4 > *pdwNumBytes)
  579. {
  580. BapTrace("Not enough space in pbPhoneDelta. Delta: %s. "
  581. "Bytes available: %d",
  582. szOurPhoneNumber + dwDeltaIndex, *pdwNumBytes);
  583. goto LDone;
  584. }
  585. // We have a phone delta
  586. fRet = TRUE;
  587. // See the format for writing Phone-Deltas in the BAPCB documentation.
  588. pbPhoneDelta[0] = (BYTE) dwNumCharsUnique;
  589. pbPhoneDelta[1] = 0;
  590. lstrcpy(pbPhoneDelta + 2, szOurPhoneNumber + dwDeltaIndex);
  591. pbPhoneDelta[dwNumCharsUnique + 2] = 0;
  592. pbPhoneDelta[dwNumCharsUnique + 3] = 0;
  593. *pdwNumBytes -= dwNumCharsUnique + 4;
  594. LDone:
  595. return(fRet);
  596. }
  597. /*
  598. Returns:
  599. TRUE: Success
  600. FALSE: Failure
  601. Description:
  602. Reads the Phone-Delta in pbPhoneDelta into szPeerPhoneNumber using
  603. szBasePhoneNumber as the "previously known number".
  604. If szBasePhoneNumber is NULL, it writes only the Phone-Delta into
  605. szPeerPhoneNumber.
  606. If the Phone-Delta is larger than the szBasePhoneNumber, it writes only the
  607. last strlen(szBasePhoneNumber) number of digits into szPeerPhoneNumber. If
  608. szBasePhoneNumber is 882 5759, and the delta is 425 713 5748, we should
  609. dial 713 5748, not the whole number.
  610. If szBasePhoneNumber is not NULL and contains an empty string,
  611. szPeerPhoneNumber is written to it.
  612. It returns the number of bytes read from pbPhoneDelta in *pdwBytesRead.
  613. */
  614. BOOL
  615. FReadPhoneDelta(
  616. OUT CHAR* szPeerPhoneNumber,
  617. IN CHAR* szBasePhoneNumber,
  618. IN BYTE* pbPhoneDelta,
  619. OUT DWORD* pdwBytesRead)
  620. {
  621. DWORD dwNumCharsPhoneNumber;
  622. DWORD dwNumCharsBase = 0;
  623. DWORD dwNumCharsDelta;
  624. DWORD dwDeltaIndex;
  625. DWORD dwNumCharsUnique;
  626. PPP_ASSERT(NULL != szPeerPhoneNumber);
  627. PPP_ASSERT(NULL != pbPhoneDelta);
  628. if (NULL != szBasePhoneNumber)
  629. {
  630. dwNumCharsBase = lstrlen(szBasePhoneNumber);
  631. }
  632. dwNumCharsDelta = pbPhoneDelta[0];
  633. // FReadOptions() makes sure that the bytes in the Subscriber-Number are all
  634. // ASCII digits.
  635. if (0xFF == dwNumCharsDelta)
  636. {
  637. // Unique-Digits is 0. See BAPCB comments.
  638. if (NULL != szBasePhoneNumber)
  639. {
  640. lstrcpy(szPeerPhoneNumber, szBasePhoneNumber);
  641. *pdwBytesRead = 1;
  642. return(TRUE);
  643. }
  644. else
  645. {
  646. BapTrace("Unique-Digits is 0, but there is no "
  647. "\"previously known number\"");
  648. return(FALSE);
  649. }
  650. }
  651. else if (0 == dwNumCharsBase)
  652. {
  653. // Note that pbPhoneDelta contains only the unique digits part of the
  654. // Subscriber-Number Sub-Option. The leading non unique digits sent by
  655. // the peer are ignored. See the BAPCB comments.
  656. lstrcpy(szPeerPhoneNumber, pbPhoneDelta + 2);
  657. }
  658. else
  659. {
  660. // If szBasePhoneNumber were NULL, we would have
  661. // (0 == dwNumCharsBase) above
  662. PPP_ASSERT(NULL != szBasePhoneNumber);
  663. if (dwNumCharsDelta > dwNumCharsBase)
  664. {
  665. // If szBasePhoneNumber is 882 5759, and the peer sent us
  666. // 425 713 5748, we should dial 713 5748, not the whole number.
  667. lstrcpy(szPeerPhoneNumber,
  668. pbPhoneDelta + 2 + dwNumCharsDelta - dwNumCharsBase);
  669. }
  670. else
  671. {
  672. lstrcpy(szPeerPhoneNumber, szBasePhoneNumber);
  673. lstrcpy(szPeerPhoneNumber + dwNumCharsBase - dwNumCharsDelta,
  674. pbPhoneDelta + 2);
  675. }
  676. }
  677. if ( (NULL != szBasePhoneNumber)
  678. && (0 == szBasePhoneNumber[0]))
  679. {
  680. lstrcpy(szBasePhoneNumber, szPeerPhoneNumber);
  681. }
  682. *pdwBytesRead = 2 + lstrlen(pbPhoneDelta + 2) + 1;
  683. *pdwBytesRead += lstrlen(pbPhoneDelta + *pdwBytesRead) + 1;
  684. return(TRUE);
  685. }
  686. /*
  687. Returns:
  688. TRUE: Success
  689. FALSE: Failure
  690. Description:
  691. This function must only be called by clients or routers.
  692. It tries to find a free link in the entry szEntryName in the phone book
  693. szPhonebookPath. fCallOut is TRUE iff we will dial out on the link. fRouter
  694. is TRUE iff we are a router. szTextualSid contains the textual sid of the
  695. logged on user. It is required iff pbPhoneDelta is not NULL and fRouter is
  696. FALSE.
  697. If *pdwLinkType is 0, it doesn't care about the link type and sets
  698. *pdwLinkType and *pdwLinkSpeed (link speed in kbps). Otherwise, the type of
  699. the free link must match *pdwLinkType. The link type is the same as the
  700. Link Type in the Link-Type BAP option: 1 for ISDN, 2 for X.25, and 4 for
  701. modem.
  702. If szPeerPhoneNumber is not NULL, it fills it up with the peer's phone
  703. number (the number that we will have to dial). If pbPhoneDelta is not NULL,
  704. it fills it up with one (!fRouter) or more (fRouter) Phone-Deltas (the
  705. numbers that the peer will have to dial). Each Phone-Delta is calculated
  706. with szBasePhoneNumber as the "previously known number". szBasePhoneNumber
  707. MUST be NULL if we are not the server. A non-router client does not want
  708. to do multiple RasPortListen()'s, and hence will send only one Phone-Delta.
  709. If pdwSubEntryIndex is not NULL, the 1-based index of the subentry in
  710. szEntryName that corresponds to the free link is put in *pdwSubEntryIndex.
  711. If szPortName is not NULL, it fills it up with the name of the port
  712. corresponding to the free link. szPortName is needed to do a
  713. RasPortListen().
  714. Sanity check: If *pdwLinkType is 0 (any link will do), pbPhoneDelta must be
  715. NULL. Ie if we are NAK'ing a request, we mustn't send any Phone-Delta.
  716. NOTE: NOTE: NOTE: NOTE: NOTE:
  717. This function is very similar to FGetAvailableLinkNonRouterServer(). If you
  718. change one, you probably need to change the other too.
  719. */
  720. BOOL
  721. FGetAvailableLinkClientOrRouter(
  722. IN PCB* pPcbLocal,
  723. IN CHAR* szPhonebookPath,
  724. IN CHAR* szEntryName,
  725. IN BOOL fCallOut,
  726. IN BOOL fRouter,
  727. IN CHAR* szTextualSid,
  728. IN OUT DWORD* pdwLinkType,
  729. IN OUT DWORD* pdwLinkSpeed,
  730. OUT CHAR* szPeerPhoneNumber,
  731. OUT DWORD* pdwSubEntryIndex,
  732. OUT BYTE* pbPhoneDelta,
  733. OUT CHAR* szPortName,
  734. IN CHAR* szBasePhoneNumber
  735. )
  736. {
  737. BOOL fRet = FALSE;
  738. DWORD dwErr;
  739. RASMAN_PORT* pRasmanPort = NULL;
  740. DWORD dwNumPorts;
  741. RASENTRY* pRasEntry = NULL;
  742. DWORD dwBufferSize;
  743. DWORD dwSubEntryIndex;
  744. RASSUBENTRY* pRasSubEntry = NULL;
  745. DWORD dwPcbIndex;
  746. DWORD dwPortIndex;
  747. RASMAN_INFO RasmanInfo;
  748. DWORD dwLinkType;
  749. DWORD dwLinkSpeed;
  750. CHAR szOurPhoneNumber[RAS_MaxCallbackNumber + 2]; // MULTI_SZ
  751. DWORD dwNumChars;
  752. BOOL fPortAvailable;
  753. RASMAN_USAGE RasmanUsage;
  754. BOOL fExitOuterFor;
  755. PPP_ASSERT(NULL != szPhonebookPath);
  756. PPP_ASSERT(NULL != szEntryName);
  757. PPP_ASSERT(NULL != pdwLinkType);
  758. PPP_ASSERT(NULL != pdwLinkSpeed);
  759. // We do this in order to keep szOurPhoneNumber a MULTI_SZ
  760. ZeroMemory(szOurPhoneNumber, RAS_MaxCallbackNumber + 2);
  761. // We don't care about the link type. Any link will do.
  762. if (0 == *pdwLinkType)
  763. {
  764. // Set *pdwLinkSpeed, in case we return an error.
  765. *pdwLinkSpeed = 0;
  766. }
  767. if (!FEnumPorts(&pRasmanPort, &dwNumPorts))
  768. {
  769. goto LDone;
  770. }
  771. if (NULL != pbPhoneDelta)
  772. {
  773. // FWritePhoneDelta will write Phone-Delta's into pbPhoneDelta. We want
  774. // the very next byte to be 0. (See BAPCB documentation).
  775. ZeroMemory(pbPhoneDelta, BAP_PHONE_DELTA_SIZE + 1);
  776. // The size (in bytes) of pbPhoneDelta available. Note that the last
  777. // byte is reserved for the terminating 0, which is why we do not set
  778. // dwNumChars to BAP_PHONE_DELTA_SIZE + 1;
  779. dwNumChars = BAP_PHONE_DELTA_SIZE;
  780. }
  781. dwBufferSize = 0;
  782. dwErr = RasGetEntryProperties(szPhonebookPath, szEntryName, NULL,
  783. &dwBufferSize, NULL, NULL);
  784. if (ERROR_BUFFER_TOO_SMALL != dwErr)
  785. {
  786. BapTrace("RasGetEntryProperties(%s, %s) returned error %d",
  787. szPhonebookPath, szEntryName, dwErr);
  788. goto LDone;
  789. }
  790. pRasEntry = LOCAL_ALLOC(LPTR, dwBufferSize);
  791. if (NULL == pRasEntry)
  792. {
  793. BapTrace("FGetAvailableLinkClientOrRouter: Out of memory.");
  794. goto LDone;
  795. }
  796. pRasEntry->dwSize = sizeof(RASENTRY);
  797. dwErr = RasGetEntryProperties(szPhonebookPath, szEntryName, pRasEntry,
  798. &dwBufferSize, NULL, NULL);
  799. if (0 != dwErr)
  800. {
  801. BapTrace("RasGetEntryProperties(%s, %s) returned error %d",
  802. szPhonebookPath, szEntryName, dwErr);
  803. goto LDone;
  804. }
  805. fExitOuterFor = FALSE;
  806. for (dwSubEntryIndex = 1;
  807. dwSubEntryIndex <= pRasEntry->dwSubEntries;
  808. dwSubEntryIndex++)
  809. {
  810. pRasSubEntry = NULL;
  811. for (dwPcbIndex = 0;
  812. dwPcbIndex < pPcbLocal->pBcb->dwPpcbArraySize;
  813. dwPcbIndex++)
  814. {
  815. if ( (NULL != pPcbLocal->pBcb->ppPcb[dwPcbIndex])
  816. && (dwSubEntryIndex ==
  817. pPcbLocal->pBcb->ppPcb[dwPcbIndex]->dwSubEntryIndex))
  818. {
  819. // This sub entry is already connected
  820. goto LOuterForEnd;
  821. }
  822. }
  823. dwBufferSize = 0;
  824. dwErr = RasGetSubEntryProperties(szPhonebookPath, szEntryName,
  825. dwSubEntryIndex, NULL, &dwBufferSize, NULL, NULL);
  826. if (ERROR_BUFFER_TOO_SMALL != dwErr)
  827. {
  828. BapTrace("RasGetSubEntryProperties(%s, %s, %d) returned error %d",
  829. szPhonebookPath, szEntryName, dwSubEntryIndex, dwErr);
  830. goto LOuterForEnd;
  831. }
  832. pRasSubEntry = LOCAL_ALLOC(LPTR, dwBufferSize);
  833. if (NULL == pRasSubEntry)
  834. {
  835. BapTrace("FGetAvailableLinkClientOrRouter: Out of memory.");
  836. goto LOuterForEnd;
  837. }
  838. pRasSubEntry->dwSize = sizeof(RASSUBENTRY);
  839. dwErr = RasGetSubEntryProperties(szPhonebookPath, szEntryName,
  840. dwSubEntryIndex, pRasSubEntry, &dwBufferSize, NULL, NULL);
  841. if (0 != dwErr)
  842. {
  843. BapTrace("RasGetSubEntryProperties(%s, %s, %d) returned error %d",
  844. szPhonebookPath, szEntryName, dwSubEntryIndex, dwErr);
  845. goto LOuterForEnd;
  846. }
  847. for (dwPortIndex = 0;
  848. dwPortIndex < dwNumPorts;
  849. dwPortIndex++)
  850. {
  851. // For each sub entry, find the port that corresponds to it. See if
  852. // it is available.
  853. if (lstrcmpi(pRasmanPort[dwPortIndex].P_DeviceName,
  854. pRasSubEntry->szDeviceName))
  855. {
  856. // This is not the port we want
  857. continue;
  858. }
  859. RasmanUsage = pRasmanPort[dwPortIndex].P_ConfiguredUsage;
  860. if (fRouter)
  861. {
  862. // Make sure that the port is a router port.
  863. if (!(RasmanUsage & CALL_ROUTER))
  864. {
  865. continue;
  866. }
  867. }
  868. else
  869. {
  870. // If fCallOut is TRUE, make sure that we can call out on this
  871. // port.
  872. if (fCallOut && !(RasmanUsage & CALL_OUT))
  873. {
  874. continue;
  875. }
  876. }
  877. dwErr = RasGetInfo(NULL, pRasmanPort[dwPortIndex].P_Handle,
  878. &RasmanInfo);
  879. fPortAvailable = FALSE;
  880. if (ERROR_PORT_NOT_OPEN == dwErr)
  881. {
  882. /*
  883. If fCallOut is TRUE, we will call RasDial().
  884. ERROR_PORT_NOT_OPEN is good. Otherwise, if we are not the
  885. router, we will call RasPortOpen() and RasPortListen(), so it
  886. is fine. The port is unacceptable *iff* a router wants to
  887. listen on it.
  888. */
  889. fPortAvailable = fCallOut || !fRouter;
  890. }
  891. else if ((LISTENING == RasmanInfo.RI_ConnState) &&
  892. ((RasmanUsage & CALL_ROUTER) ||
  893. (RasmanUsage & CALL_IN)))
  894. {
  895. /*
  896. We can use the port if the server or the router is doing a
  897. listen. We cannot use the port if it is in the LISTENING state
  898. because a client called RasDial() on it and is expecting a
  899. callback. If neither CALL_ROUTER nor CALL_IN is true, we know
  900. that it is a client doing a listen. Otherwise, we don't know,
  901. but we will assume that it is available and handle errors
  902. later.
  903. */
  904. fPortAvailable = TRUE;
  905. }
  906. if (!fPortAvailable)
  907. {
  908. continue;
  909. }
  910. if (!FGetLinkTypeAndSpeedFromRasmanPort(
  911. pRasmanPort + dwPortIndex, &dwLinkType, &dwLinkSpeed))
  912. {
  913. continue;
  914. }
  915. if (0 == *pdwLinkType)
  916. {
  917. *pdwLinkType = dwLinkType;
  918. *pdwLinkSpeed = dwLinkSpeed;
  919. }
  920. else if (dwLinkType != *pdwLinkType)
  921. {
  922. continue;
  923. }
  924. if (szPortName)
  925. {
  926. lstrcpy(szPortName, pRasmanPort[dwPortIndex].P_PortName);
  927. }
  928. if (pbPhoneDelta)
  929. {
  930. // If our phone number is requested and we cannot supply it, we
  931. // must return FALSE.
  932. if (!FGetOurPhoneNumberFromPortName(
  933. pRasmanPort[dwPortIndex].P_PortName,
  934. szOurPhoneNumber, fRouter, szTextualSid))
  935. {
  936. continue;
  937. }
  938. if (!FWritePhoneDelta(szOurPhoneNumber, szBasePhoneNumber,
  939. pbPhoneDelta + BAP_PHONE_DELTA_SIZE - dwNumChars,
  940. &dwNumChars))
  941. {
  942. continue;
  943. }
  944. }
  945. if (szPeerPhoneNumber)
  946. {
  947. lstrcpy(szPeerPhoneNumber, pRasSubEntry->szLocalPhoneNumber);
  948. }
  949. if (pdwSubEntryIndex)
  950. {
  951. *pdwSubEntryIndex = dwSubEntryIndex;
  952. }
  953. BapTrace("FGetAvailableLinkClientOrRouter: Portname is %s",
  954. pRasmanPort[dwPortIndex].P_PortName);
  955. fRet = TRUE;
  956. if (!pbPhoneDelta || !fRouter)
  957. {
  958. // We don't want to collect all our Phone-Deltas.
  959. fExitOuterFor = TRUE;
  960. goto LOuterForEnd;
  961. }
  962. }
  963. LOuterForEnd:
  964. if (NULL != pRasSubEntry)
  965. {
  966. LOCAL_FREE(pRasSubEntry);
  967. }
  968. if (fExitOuterFor)
  969. {
  970. break;
  971. }
  972. }
  973. LDone:
  974. if (NULL != pRasmanPort)
  975. {
  976. LOCAL_FREE(pRasmanPort);
  977. }
  978. if (NULL != pRasEntry)
  979. {
  980. LOCAL_FREE(pRasEntry);
  981. }
  982. return(fRet);
  983. }
  984. /*
  985. Returns:
  986. TRUE: Success
  987. FALSE: Failure
  988. Description:
  989. This function must only be called by servers that are not routers.
  990. It tries to find a free link that the server can use. fCallOut is TRUE iff
  991. we will dial out on the link. If *pdwLinkType is 0, it doesn't care about
  992. the link type and sets *pdwLinkType and *pdwLinkSpeed (link speed in kbps).
  993. Otherwise, the type of the free link must match *pdwLinkType. The link type
  994. is the same as the Link Type in the Link-Type BAP option: 1 for ISDN, 2 for
  995. X.25, and 4 for modem.
  996. If fCallOut is TRUE, the handle of the port that the server will call out
  997. on will be put in *phPort.
  998. If pbPhoneDelta is not NULL, it fills it up with our Phone-Deltas (the
  999. numbers that the peer can dial). Each Phone-Delta is calculated with
  1000. szBasePhoneNumber as the "previously known number". szBasePhoneNumber can
  1001. be NULL.
  1002. Sanity check: If *pdwLinkType is 0 (any link will do), pbPhoneDelta must be
  1003. NULL. Ie if we are NAK'ing a request, we mustn't send any Phone-Delta.
  1004. NOTE: NOTE: NOTE: NOTE: NOTE:
  1005. This function is very similar to FGetAvailableLinkClientOrRouter(). If you
  1006. change one, you probably need to change the other too.
  1007. */
  1008. BOOL
  1009. FGetAvailableLinkNonRouterServer(
  1010. IN BOOL fCallOut,
  1011. IN OUT DWORD* pdwLinkType,
  1012. IN OUT DWORD* pdwLinkSpeed,
  1013. OUT HPORT* phPort,
  1014. OUT BYTE* pbPhoneDelta,
  1015. IN CHAR* szBasePhoneNumber
  1016. )
  1017. {
  1018. BOOL fRet = FALSE;
  1019. DWORD dwErr;
  1020. RASMAN_PORT* pRasmanPort = NULL;
  1021. DWORD dwNumPorts;
  1022. DWORD dwPortIndex;
  1023. RASMAN_INFO RasmanInfo;
  1024. DWORD dwLinkType;
  1025. DWORD dwLinkSpeed;
  1026. CHAR szOurPhoneNumber[RAS_MaxCallbackNumber + 1];
  1027. DWORD dwNumChars;
  1028. BOOL fPortAvailable;
  1029. RASMAN_USAGE RasmanUsage;
  1030. PPP_ASSERT(NULL != pdwLinkType);
  1031. PPP_ASSERT(NULL != pdwLinkSpeed);
  1032. // We don't care about the link type. Any link will do.
  1033. if (0 == *pdwLinkType)
  1034. {
  1035. // Set *pdwLinkSpeed, in case we return an error.
  1036. // We shouldn't be sending a Phone-Delta if we are NAK'ing a
  1037. // Call-Request or Callback-Request and sending a Link-Type
  1038. PPP_ASSERT(NULL == pbPhoneDelta);
  1039. *pdwLinkSpeed = 0;
  1040. }
  1041. if (!FEnumPorts(&pRasmanPort, &dwNumPorts))
  1042. {
  1043. goto LDone;
  1044. }
  1045. if (NULL != pbPhoneDelta)
  1046. {
  1047. // FWritePhoneDelta will write Phone-Delta's into pbPhoneDelta. We want
  1048. // the very next byte to be 0. (See BAPCB documentation).
  1049. ZeroMemory(pbPhoneDelta, BAP_PHONE_DELTA_SIZE + 1);
  1050. // The size (in bytes) of pbPhoneDelta available. Note that the last
  1051. // byte is reserved for the terminating 0, which is why we do not set
  1052. // dwNumChars to BAP_PHONE_DELTA_SIZE + 1;
  1053. dwNumChars = BAP_PHONE_DELTA_SIZE;
  1054. }
  1055. for (dwPortIndex = 0; dwPortIndex < dwNumPorts; dwPortIndex++)
  1056. {
  1057. RasmanUsage = pRasmanPort[dwPortIndex].P_ConfiguredUsage;
  1058. // If fCallOut is TRUE, make sure that we can call out on this
  1059. // port. Else, make sure that we can accept calls on this port.
  1060. if ((fCallOut && !(RasmanUsage & CALL_OUT)) ||
  1061. (!fCallOut && !(RasmanUsage & CALL_IN)))
  1062. {
  1063. continue;
  1064. }
  1065. dwErr = RasGetInfo(NULL, pRasmanPort[dwPortIndex].P_Handle, &RasmanInfo);
  1066. fPortAvailable = FALSE;
  1067. if (ERROR_PORT_NOT_OPEN == dwErr)
  1068. {
  1069. /*
  1070. If fCallOut is TRUE, we will open the port and call out, so
  1071. ERROR_PORT_NOT_OPEN is fine. Otherwise, the port is unacceptable.
  1072. */
  1073. fPortAvailable = fCallOut;
  1074. }
  1075. else if ( NO_ERROR != dwErr)
  1076. {
  1077. continue;
  1078. }
  1079. else if ((LISTENING == RasmanInfo.RI_ConnState) &&
  1080. ((RasmanUsage & CALL_ROUTER) ||
  1081. (RasmanUsage & CALL_IN)))
  1082. {
  1083. /*
  1084. We can use the port if the server or the router is doing a listen.
  1085. We cannot use the port if it is in the LISTENING state because
  1086. a client called RasDial() on it and is expecting a callback. If
  1087. neither CALL_ROUTER nor CALL_IN is true, we know that it is a
  1088. client doing a listen. Otherwise, we don't know, but we will
  1089. assume that it is available and handle errors later.
  1090. */
  1091. fPortAvailable = TRUE;
  1092. }
  1093. if (!fPortAvailable)
  1094. {
  1095. continue;
  1096. }
  1097. if (!FGetLinkTypeAndSpeedFromRasmanPort(
  1098. pRasmanPort + dwPortIndex, &dwLinkType, &dwLinkSpeed))
  1099. {
  1100. continue;
  1101. }
  1102. if (0 == *pdwLinkType)
  1103. {
  1104. *pdwLinkType = dwLinkType;
  1105. *pdwLinkSpeed = dwLinkSpeed;
  1106. }
  1107. else if (dwLinkType != *pdwLinkType)
  1108. {
  1109. continue;
  1110. }
  1111. if (phPort)
  1112. {
  1113. *phPort = pRasmanPort[dwPortIndex].P_Handle;
  1114. }
  1115. if (pbPhoneDelta)
  1116. {
  1117. // If our phone number is requested and we cannot supply it, we
  1118. // must return FALSE.
  1119. if (!FGetOurPhoneNumberFromHPort(
  1120. pRasmanPort[dwPortIndex].P_Handle,
  1121. szOurPhoneNumber))
  1122. {
  1123. continue;
  1124. }
  1125. if (!FWritePhoneDelta(szOurPhoneNumber, szBasePhoneNumber,
  1126. pbPhoneDelta + BAP_PHONE_DELTA_SIZE - dwNumChars,
  1127. &dwNumChars))
  1128. {
  1129. continue;
  1130. }
  1131. }
  1132. BapTrace("FGetAvailableLinkNonRouterServer: Portname is %s",
  1133. pRasmanPort[dwPortIndex].P_PortName);
  1134. fRet = TRUE;
  1135. if (!pbPhoneDelta)
  1136. {
  1137. // We don't want to collect all our Phone-Deltas.
  1138. break;
  1139. }
  1140. }
  1141. LDone:
  1142. if (NULL != pRasmanPort)
  1143. {
  1144. LOCAL_FREE(pRasmanPort);
  1145. }
  1146. return(fRet);
  1147. }
  1148. /*
  1149. Returns:
  1150. TRUE: Success
  1151. FALSE: Failure
  1152. Description:
  1153. If fServer is TRUE, it calls FGetAvailableLinkNonRouterServer() with the
  1154. appropriate arguments. Otherwise it calls FGetAvailableLinkClientOrRouter().
  1155. */
  1156. BOOL
  1157. FGetAvailableLink(
  1158. IN PCB* pPcbLocal,
  1159. IN BOOL fServer,
  1160. IN BOOL fRouter,
  1161. IN BOOL fCallOut,
  1162. IN CHAR* szPhonebookPath,
  1163. IN CHAR* szEntryName,
  1164. IN CHAR* szTextualSid,
  1165. IN OUT DWORD* pdwLinkType,
  1166. IN OUT DWORD* pdwLinkSpeed,
  1167. OUT CHAR* szPeerPhoneNumber,
  1168. OUT DWORD* pdwSubEntryIndex,
  1169. OUT HPORT* phPort,
  1170. OUT BYTE* pbPhoneDelta,
  1171. OUT CHAR* szPortName,
  1172. IN CHAR* szBasePhoneNumber
  1173. )
  1174. {
  1175. if (fServer && !fRouter)
  1176. {
  1177. return(FGetAvailableLinkNonRouterServer(
  1178. fCallOut,
  1179. pdwLinkType,
  1180. pdwLinkSpeed,
  1181. phPort,
  1182. pbPhoneDelta,
  1183. szBasePhoneNumber));
  1184. }
  1185. else
  1186. {
  1187. return(FGetAvailableLinkClientOrRouter(
  1188. pPcbLocal,
  1189. szPhonebookPath,
  1190. szEntryName,
  1191. fCallOut,
  1192. fRouter,
  1193. szTextualSid,
  1194. pdwLinkType,
  1195. pdwLinkSpeed,
  1196. szPeerPhoneNumber,
  1197. pdwSubEntryIndex,
  1198. pbPhoneDelta,
  1199. szPortName,
  1200. szBasePhoneNumber));
  1201. }
  1202. }
  1203. /*
  1204. Returns:
  1205. VOID
  1206. Description:
  1207. The PPP thread mustn't call RasDial. Otherwise, a deadlock will occur in
  1208. the following case. The user tries to hang up a connectoid from the UI.
  1209. RasHangUp acquires csStopLock, calls StopPPP, and waits for StopPPP to
  1210. return. Meanwhile, if the PPP thread calls RasDial, it will wait for
  1211. csStopLock.
  1212. */
  1213. VOID
  1214. RasDialThreadFunc(
  1215. IN VOID* pVoid
  1216. )
  1217. {
  1218. RASDIAL_ARGS* pRasDialArgs = pVoid;
  1219. RASDIALPARAMS* pRasDialParams;
  1220. HRASCONN hRasConn = NULL;
  1221. HRASCONN hRasConnSubEntry = NULL;
  1222. PCB_WORK_ITEM* pWorkItem;
  1223. DWORD dwErr;
  1224. PPP_ASSERT(NULL != pRasDialArgs);
  1225. pRasDialParams = &(pRasDialArgs->RasDialParams);
  1226. BapTrace("Dialing %s using %s(%d)...",
  1227. pRasDialParams->szPhoneNumber,
  1228. pRasDialParams->szEntryName,
  1229. pRasDialParams->dwSubEntry);
  1230. DecodePw(pRasDialArgs->chSeed, pRasDialArgs->RasDialParams.szPassword);
  1231. dwErr = RasDial(
  1232. &(pRasDialArgs->RasDialExtensions),
  1233. pRasDialArgs->szPhonebookPath,
  1234. &(pRasDialArgs->RasDialParams),
  1235. 2 /* dwNotifierType */,
  1236. NULL,
  1237. &hRasConn);
  1238. EncodePw(pRasDialArgs->chSeed, pRasDialArgs->RasDialParams.szPassword);
  1239. BapTrace(" ");
  1240. BapTrace("RasDial returned %d on HCONN 0x%x",
  1241. dwErr, pRasDialArgs->RasDialParams.dwCallbackId);
  1242. if (NO_ERROR != dwErr)
  1243. {
  1244. goto LDone;
  1245. }
  1246. // By this time, PPP has been negotiated on the new link and the new link
  1247. // has been bundled or not (if the user disconnected the connection). If it
  1248. // has not been bundled, then pRasDialArgs->hRasConn is invalid and
  1249. // RasGetSubEntryHandle will fail.
  1250. if (pRasDialArgs->fServerRouter)
  1251. {
  1252. hRasConnSubEntry = hRasConn;
  1253. }
  1254. else
  1255. {
  1256. dwErr = RasGetSubEntryHandle(pRasDialArgs->hRasConn,
  1257. pRasDialParams->dwSubEntry, &hRasConnSubEntry);
  1258. if (NO_ERROR != dwErr)
  1259. {
  1260. BapTrace("RasGetSubEntryHandle failed and returned %d", dwErr);
  1261. goto LDone;
  1262. }
  1263. }
  1264. LDone:
  1265. pWorkItem = (PCB_WORK_ITEM*) LOCAL_ALLOC(LPTR, sizeof(PCB_WORK_ITEM));
  1266. if (pWorkItem == NULL)
  1267. {
  1268. dwErr = GetLastError();
  1269. BapTrace("Couldn't allocate memory for ProcessCallResult");
  1270. }
  1271. else
  1272. {
  1273. // Inform the worker thread that we know the result of the
  1274. // call attempt.
  1275. pWorkItem->Process = ProcessCallResult;
  1276. pWorkItem->hConnection = (HCONN)
  1277. (pRasDialArgs->RasDialParams.dwCallbackId);
  1278. pWorkItem->PppMsg.BapCallResult.dwResult = dwErr;
  1279. pWorkItem->PppMsg.BapCallResult.hRasConn = hRasConnSubEntry;
  1280. InsertWorkItemInQ(pWorkItem);
  1281. }
  1282. if (NO_ERROR != dwErr)
  1283. {
  1284. if (NULL != hRasConnSubEntry)
  1285. {
  1286. // Perhaps we couldn't alloc a PCB_WORK_ITEM.
  1287. dwErr = RasHangUp(hRasConnSubEntry);
  1288. }
  1289. if (NULL != hRasConn)
  1290. {
  1291. dwErr = RasHangUp(hRasConn);
  1292. }
  1293. if (0 != dwErr)
  1294. {
  1295. BapTrace("RasHangup failed and returned %d", dwErr);
  1296. }
  1297. }
  1298. if (NULL != pRasDialArgs->pbEapInfo)
  1299. {
  1300. LOCAL_FREE(pRasDialArgs->pbEapInfo);
  1301. }
  1302. LOCAL_FREE(pRasDialArgs->szPhonebookPath);
  1303. LOCAL_FREE(pRasDialArgs);
  1304. }
  1305. /*
  1306. Returns:
  1307. TRUE: Success
  1308. FALSE: Failure
  1309. Description:
  1310. Places a call to the peer. pBcbLocal represents the bundle that wants to
  1311. call.
  1312. */
  1313. BOOL
  1314. FCall(
  1315. IN BCB* pBcbLocal
  1316. )
  1317. {
  1318. NTSTATUS Status;
  1319. DWORD dwErr;
  1320. BAPCB* pBapCbLocal;
  1321. PPP_MESSAGE PppMsg;
  1322. BOOL fRouter;
  1323. BOOL fServer;
  1324. BOOL fClientOrRouter;
  1325. DWORD dwBytesRead;
  1326. PCB* pPcbLocal;
  1327. BOOL fRet = FALSE;
  1328. RASMAN_INFO RasmanInfo;
  1329. RASDIAL_ARGS* pRasDialArgs = NULL;
  1330. RASDIALPARAMS* pRasDialParams;
  1331. RASDIALEXTENSIONS* pRasDialExtensions;
  1332. PPP_ASSERT(NULL != pBcbLocal);
  1333. pBapCbLocal = &(pBcbLocal->BapCb);
  1334. pRasDialArgs = LOCAL_ALLOC(LPTR, sizeof(RASDIAL_ARGS));
  1335. if (NULL == pRasDialArgs)
  1336. {
  1337. BapTrace("Out of memory. Can't call on HCONN 0x%x",
  1338. pBcbLocal->hConnection);
  1339. goto LDone;
  1340. }
  1341. pRasDialArgs->chSeed = pBcbLocal->chSeed;
  1342. pRasDialParams = &(pRasDialArgs->RasDialParams);
  1343. pRasDialExtensions = &(pRasDialArgs->RasDialExtensions);
  1344. fServer = (pBcbLocal->fFlags & BCBFLAG_IS_SERVER) != 0;
  1345. fRouter =
  1346. (ROUTER_IF_TYPE_FULL_ROUTER == pBcbLocal->InterfaceInfo.IfType);
  1347. fClientOrRouter = !fServer || fRouter;
  1348. ZeroMemory(&PppMsg, sizeof(PppMsg));
  1349. if (!pBapCbLocal->fPeerSuppliedPhoneNumber)
  1350. {
  1351. PPP_ASSERT(fClientOrRouter);
  1352. pRasDialParams->szPhoneNumber[0] = 0;
  1353. }
  1354. else
  1355. {
  1356. PPP_ASSERT(NULL != pBapCbLocal->pbPhoneDeltaRemote);
  1357. if (!FReadPhoneDelta(
  1358. fClientOrRouter ?
  1359. pRasDialParams->szPhoneNumber :
  1360. PppMsg.ExtraInfo.BapCallbackRequest.szCallbackNumber,
  1361. fServer ? pBapCbLocal->szClientPhoneNumber :
  1362. pBapCbLocal->szServerPhoneNumber,
  1363. pBapCbLocal->pbPhoneDeltaRemote +
  1364. pBapCbLocal->dwPhoneDeltaRemoteOffset,
  1365. &dwBytesRead))
  1366. {
  1367. goto LDone;
  1368. }
  1369. else
  1370. {
  1371. pBapCbLocal->dwPhoneDeltaRemoteOffset += dwBytesRead;
  1372. }
  1373. }
  1374. pPcbLocal = GetPCBPointerFromBCB(pBcbLocal);
  1375. if (NULL == pPcbLocal)
  1376. {
  1377. BapTrace("FCall: No links in HCONN 0x%x!", pBcbLocal->hConnection);
  1378. goto LDone;
  1379. }
  1380. if (!fClientOrRouter)
  1381. {
  1382. // Non-router server
  1383. // Don't call RasDial. Instead ask Ddm to call
  1384. PppMsg.hPort = pBapCbLocal->hPort;
  1385. PppMsg.dwMsgId = PPPDDMMSG_BapCallbackRequest;
  1386. PppMsg.ExtraInfo.BapCallbackRequest.hConnection =
  1387. pBcbLocal->hConnection;
  1388. PppConfigInfo.SendPPPMessageToDdm(&PppMsg);
  1389. BapTrace("Dialing %s on port %d...",
  1390. PppMsg.ExtraInfo.BapCallbackRequest.szCallbackNumber,
  1391. pBapCbLocal->hPort);
  1392. }
  1393. else
  1394. {
  1395. dwErr = RasGetInfo(NULL, pPcbLocal->hPort, &RasmanInfo);
  1396. if (NO_ERROR != dwErr)
  1397. {
  1398. BapTrace("RasGetInfo failed on hPort %d. Error: %d",
  1399. pPcbLocal->hPort, dwErr);
  1400. goto LDone;
  1401. }
  1402. pRasDialArgs->hRasConn = RasmanInfo.RI_ConnectionHandle;
  1403. pRasDialExtensions->dwSize = sizeof(RASDIALEXTENSIONS);
  1404. if (fRouter)
  1405. {
  1406. pRasDialArgs->fServerRouter = fServer;
  1407. pRasDialExtensions->dwfOptions = RDEOPT_Router;
  1408. CopyMemory(&(pRasDialArgs->InterfaceInfo),
  1409. &(pBcbLocal->InterfaceInfo), sizeof(PPP_INTERFACE_INFO));
  1410. pRasDialExtensions->reserved
  1411. = (ULONG_PTR)&(pRasDialArgs->InterfaceInfo);
  1412. }
  1413. if ( (NULL != pBcbLocal->pCustomAuthUserData)
  1414. && (0 != pBcbLocal->pCustomAuthUserData->cbCustomAuthData))
  1415. {
  1416. pRasDialArgs->pbEapInfo = LOCAL_ALLOC(LPTR,
  1417. pBcbLocal->pCustomAuthUserData->cbCustomAuthData);
  1418. if (NULL == pRasDialArgs->pbEapInfo)
  1419. {
  1420. BapTrace("Out of memory. Can't call on HCONN 0x%x",
  1421. pBcbLocal->hConnection);
  1422. goto LDone;
  1423. }
  1424. CopyMemory(pRasDialArgs->pbEapInfo,
  1425. pBcbLocal->pCustomAuthUserData->abCustomAuthData,
  1426. pBcbLocal->pCustomAuthUserData->cbCustomAuthData);
  1427. pRasDialExtensions->RasEapInfo.dwSizeofEapInfo =
  1428. pBcbLocal->pCustomAuthUserData->cbCustomAuthData;
  1429. pRasDialExtensions->RasEapInfo.pbEapInfo =
  1430. pRasDialArgs->pbEapInfo;
  1431. if (pBcbLocal->fFlags & BCBFLAG_LOGON_USER_DATA)
  1432. {
  1433. pRasDialExtensions->dwfOptions = RDEOPT_NoUser;
  1434. }
  1435. }
  1436. pRasDialParams->dwSize = sizeof(RASDIALPARAMS);
  1437. lstrcpy(pRasDialParams->szEntryName, pBcbLocal->szEntryName);
  1438. lstrcpy(pRasDialParams->szUserName, pBcbLocal->szLocalUserName);
  1439. lstrcpy(pRasDialParams->szPassword, pBcbLocal->szPassword);
  1440. lstrcpy(pRasDialParams->szDomain, pBcbLocal->szLocalDomain);
  1441. pRasDialParams->dwCallbackId = HandleToUlong(pBcbLocal->hConnection);
  1442. pRasDialParams->dwSubEntry = pBapCbLocal->dwSubEntryIndex;
  1443. pRasDialArgs->szPhonebookPath =
  1444. LOCAL_ALLOC(LPTR, strlen(pBcbLocal->szPhonebookPath) + 1);
  1445. if (NULL == pRasDialArgs->szPhonebookPath)
  1446. {
  1447. BapTrace("Out of memory. Can't call on HCONN 0x%x",
  1448. pBcbLocal->hConnection);
  1449. goto LDone;
  1450. }
  1451. lstrcpy(pRasDialArgs->szPhonebookPath, pBcbLocal->szPhonebookPath);
  1452. Status = RtlQueueWorkItem( RasDialThreadFunc, pRasDialArgs,
  1453. WT_EXECUTEDEFAULT);
  1454. if (STATUS_SUCCESS != Status)
  1455. {
  1456. BapTrace("RtlQueueWorkItem failed and returned %d", Status);
  1457. goto LDone;
  1458. }
  1459. pRasDialArgs = NULL; // This will be freed by RasDialThreadFunc
  1460. }
  1461. fRet = TRUE;
  1462. LDone:
  1463. if (NULL != pRasDialArgs)
  1464. {
  1465. if (NULL != pRasDialArgs->szPhonebookPath)
  1466. {
  1467. LOCAL_FREE(pRasDialArgs->szPhonebookPath);
  1468. }
  1469. if (NULL != pRasDialArgs->pbEapInfo)
  1470. {
  1471. LOCAL_FREE(pRasDialArgs->pbEapInfo);
  1472. }
  1473. LOCAL_FREE(pRasDialArgs);
  1474. }
  1475. return(fRet);
  1476. }
  1477. /*
  1478. Returns:
  1479. TRUE: Success
  1480. FALSE: Failure
  1481. Description:
  1482. pBcbLocal represents the bundle that wants to call. pBapCbRemote is filled
  1483. with the options sent by the peer. This function allocates
  1484. pbPhoneDeltaRemote and sets dwPhoneDeltaRemoteOffset and
  1485. fPeerSuppliedPhoneNumber in pBapCbLocal before calling FCall to do the
  1486. actual work.
  1487. */
  1488. BOOL
  1489. FCallInitial(
  1490. IN BCB* pBcbLocal,
  1491. IN BAPCB* pBapCbRemote
  1492. )
  1493. {
  1494. BAPCB* pBapCbLocal;
  1495. BOOL fCall;
  1496. BOOL fRet;
  1497. PPP_ASSERT(NULL != pBcbLocal);
  1498. PPP_ASSERT(NULL != pBapCbRemote);
  1499. pBapCbLocal = &(pBcbLocal->BapCb);
  1500. // If the peer is responding to our Call-Request and we had sent the
  1501. // No-Phone-Number-Needed option, we don't need any phone number. In all
  1502. // other cases, the peer must have supplied a phone number.
  1503. fCall = (BAP_PACKET_CALL_RESP == pBapCbRemote->dwType);
  1504. pBapCbLocal->fPeerSuppliedPhoneNumber =
  1505. !(fCall && (pBapCbLocal->dwOptions & BAP_N_NO_PH_NEEDED));
  1506. // pbPhoneDeltaRemote is initially NULL and we always set it to NULL after
  1507. // we deallocate it.
  1508. PPP_ASSERT(NULL == pBapCbLocal->pbPhoneDeltaRemote);
  1509. if (pBapCbLocal->fPeerSuppliedPhoneNumber)
  1510. {
  1511. pBapCbLocal->pbPhoneDeltaRemote =
  1512. LOCAL_ALLOC(LPTR, BAP_PHONE_DELTA_SIZE + 1);
  1513. if (NULL == pBapCbLocal->pbPhoneDeltaRemote)
  1514. {
  1515. BapTrace("Out of memory");
  1516. fRet = FALSE;
  1517. goto LDone;
  1518. }
  1519. if (NULL != pBapCbLocal->pbPhoneDeltaRemote)
  1520. {
  1521. CopyMemory(pBapCbLocal->pbPhoneDeltaRemote,
  1522. pBapCbRemote->pbPhoneDelta,
  1523. BAP_PHONE_DELTA_SIZE + 1);
  1524. pBapCbLocal->dwPhoneDeltaRemoteOffset = 0;
  1525. // FReadOptions() makes sure that there is at least one Phone-Delta
  1526. PPP_ASSERT(0 != pBapCbLocal->pbPhoneDeltaRemote[0]);
  1527. }
  1528. }
  1529. fRet = FCall(pBcbLocal);
  1530. if (!fRet)
  1531. {
  1532. if (NULL != pBapCbLocal->pbPhoneDeltaRemote)
  1533. {
  1534. LOCAL_FREE(pBapCbLocal->pbPhoneDeltaRemote);
  1535. }
  1536. pBapCbLocal->pbPhoneDeltaRemote = NULL;
  1537. }
  1538. else
  1539. {
  1540. // BapEventCallResult will get called at some point, and we will free
  1541. // pBapCbLocal->pbPhoneDeltaRemote.
  1542. }
  1543. LDone:
  1544. return(fRet);
  1545. }
  1546. /*
  1547. Returns:
  1548. TRUE: Success
  1549. FALSE: Failure
  1550. Description:
  1551. Listens for incoming calls on the port named szPortName. dwSubEntryIndex is
  1552. the index of the phonebook sub entry that corresponds to that port.
  1553. pPcbLocal is any PCB in the bbundle that wants to do the listen. This
  1554. function should be called by non-router clients only.
  1555. */
  1556. BOOL
  1557. FListenForCall(
  1558. IN CHAR* szPortName,
  1559. IN DWORD dwSubEntryIndex,
  1560. IN PCB* pPcbLocal
  1561. )
  1562. {
  1563. DWORD dwErr;
  1564. HPORT hPort;
  1565. BOOL fCloseHPort = FALSE;
  1566. PCB* pPcbOther;
  1567. PCB* pPcbNew = NULL;
  1568. DWORD dwIndex;
  1569. RASMAN_INFO RasmanInfo;
  1570. BOOL fRet = FALSE;
  1571. HCONN hConnection;
  1572. PPP_ASSERT(NULL != szPortName);
  1573. PPP_ASSERT(NULL != pPcbLocal);
  1574. hConnection = pPcbLocal->pBcb->hConnection;
  1575. dwErr = RasGetInfo(NULL, pPcbLocal->hPort, &RasmanInfo);
  1576. if (NO_ERROR != dwErr)
  1577. {
  1578. BapTrace("RasGetInfo failed on hPort %d. Error: %d",
  1579. pPcbLocal->hPort, dwErr);
  1580. goto LDone;
  1581. }
  1582. pPcbNew = (PCB *)LOCAL_ALLOC(LPTR, sizeof(PCB));
  1583. if (NULL == pPcbNew)
  1584. {
  1585. BapTrace("Out of memory. Can't accept a call on HCONN 0x%x",
  1586. hConnection);
  1587. goto LDone;
  1588. }
  1589. dwErr = AllocateAndInitBcb(pPcbNew);
  1590. if (NO_ERROR != dwErr)
  1591. {
  1592. BapTrace("Out of memory. Can't accept a call on HCONN 0x%x",
  1593. hConnection);
  1594. goto LDone;
  1595. }
  1596. dwErr = RasPortOpen(szPortName, &hPort, NULL /* notifier */);
  1597. if (NO_ERROR != dwErr)
  1598. {
  1599. BapTrace("RasPortOpen failed on HCONN 0x%x. Error: %d",
  1600. hConnection, dwErr);
  1601. goto LDone;
  1602. }
  1603. fCloseHPort = TRUE;
  1604. pPcbOther = GetPCBPointerFromhPort(hPort);
  1605. if (NULL != pPcbOther)
  1606. {
  1607. BapTrace("hPort %d not cleaned up yet", hPort);
  1608. goto LDone;
  1609. }
  1610. dwErr = RasAddConnectionPort(RasmanInfo.RI_ConnectionHandle, hPort,
  1611. dwSubEntryIndex);
  1612. if (NO_ERROR != dwErr)
  1613. {
  1614. BapTrace("RasAddConnectionPort failed with hPort %d and HRASCONN 0x%x. "
  1615. "Error: %d",
  1616. hPort, RasmanInfo.RI_ConnectionHandle, dwErr);
  1617. goto LDone;
  1618. }
  1619. dwIndex = HashPortToBucket(hPort);
  1620. dwErr = RasPortListen(hPort, PppConfigInfo.dwBapListenTimeoutSeconds,
  1621. INVALID_HANDLE_VALUE);
  1622. if (NO_ERROR != dwErr && PENDING != dwErr)
  1623. {
  1624. BapTrace("RasPortListen failed on HCONN 0x%x. Error: %d",
  1625. hConnection, dwErr);
  1626. goto LDone;
  1627. }
  1628. BapTrace("RasPortListen called on hPort %d for HCONN 0x%x",
  1629. hPort, hConnection);
  1630. pPcbNew->hPort = hPort;
  1631. pPcbNew->hConnection = hConnection;
  1632. pPcbNew->fFlags = PCBFLAG_PORT_IN_LISTENING_STATE;
  1633. lstrcpy(pPcbNew->szPortName, szPortName);
  1634. // Insert NewPcb into PCB hash table
  1635. PppLog(2, "Inserting port in bucket # %d", dwIndex);
  1636. pPcbNew->pNext = PcbTable.PcbBuckets[dwIndex].pPorts;
  1637. PcbTable.PcbBuckets[dwIndex].pPorts = pPcbNew;
  1638. fRet = TRUE;
  1639. pPcbLocal->pBcb->fFlags |= BCBFLAG_LISTENING;
  1640. LDone:
  1641. if (!fRet)
  1642. {
  1643. if (NULL != pPcbNew)
  1644. {
  1645. DeallocateAndRemoveBcbFromTable(pPcbNew->pBcb);
  1646. LOCAL_FREE(pPcbNew);
  1647. }
  1648. if (fCloseHPort)
  1649. {
  1650. RasPortClose(hPort);
  1651. }
  1652. }
  1653. return(fRet);
  1654. }
  1655. /*
  1656. Returns:
  1657. TRUE: We are willing to add a link to the bundle
  1658. FALSE: No more links in the bundle right now
  1659. Description:
  1660. Considers the bandwidth utilization on the bundle represented by pBcbLocal
  1661. and says whether the BAP policy allows us to add another link.
  1662. When the server receives a call[back] request, it will ACK if the
  1663. utilization is more than the lower threshold for the sample period and the
  1664. user's max link limit has not been reached. Otherwise, it will NAK.
  1665. When a client receives a call[back] request, it will ACK if the utilization
  1666. is more than the upper threshold for the sample period. Otherwise, it will
  1667. NAK.
  1668. */
  1669. BOOL
  1670. FOkToAddLink(
  1671. IN BCB * pBcbLocal
  1672. )
  1673. {
  1674. PCB* pPcbLocal;
  1675. RAS_GET_BANDWIDTH_UTILIZATION Util;
  1676. DWORD dwLowThreshold;
  1677. DWORD dwHighThreshold;
  1678. DWORD dwUpPeriod;
  1679. DWORD dwDownPeriod;
  1680. DWORD dwErr;
  1681. return(TRUE);
  1682. #if 0
  1683. pPcbLocal = GetPCBPointerFromBCB(pBcbLocal);
  1684. if (NULL == pPcbLocal)
  1685. {
  1686. BapTrace("FOkToAddLink: No links in HCONN 0x%x!",
  1687. pBcbLocal->hConnection);
  1688. return(FALSE);
  1689. }
  1690. dwErr = RasGetBandwidthUtilization(pPcbLocal->hPort, &Util);
  1691. if (NO_ERROR != dwErr)
  1692. {
  1693. BapTrace("RasGetBandwidthUtilization failed and returned %d", dwErr);
  1694. return(FALSE);
  1695. }
  1696. dwDownPeriod = pBcbLocal->BapParams.dwHangUpExtraSampleSeconds;
  1697. dwUpPeriod = pBcbLocal->BapParams.dwDialExtraSampleSeconds;
  1698. BapTrace("Utilization: "
  1699. "%d sec: (Xmit: %d%%, Recv: %d%%), "
  1700. "%d sec: (Xmit: %d%%, Recv: %d%%)",
  1701. dwUpPeriod, Util.ulUpperXmitUtil, Util.ulUpperRecvUtil,
  1702. dwDownPeriod, Util.ulLowerXmitUtil, Util.ulLowerRecvUtil);
  1703. dwLowThreshold = pBcbLocal->BapParams.dwHangUpExtraPercent;
  1704. dwHighThreshold = pBcbLocal->BapParams.dwDialExtraPercent;
  1705. if (pBcbLocal->fFlags & BCBFLAG_IS_SERVER)
  1706. {
  1707. if ( (Util.ulLowerXmitUtil > dwLowThreshold)
  1708. || (Util.ulLowerRecvUtil > dwLowThreshold))
  1709. {
  1710. return(TRUE);
  1711. }
  1712. }
  1713. else
  1714. {
  1715. if ( (Util.ulUpperXmitUtil > dwHighThreshold)
  1716. || (Util.ulUpperRecvUtil > dwHighThreshold))
  1717. {
  1718. return(TRUE);
  1719. }
  1720. }
  1721. return(FALSE);
  1722. #endif
  1723. }
  1724. /*
  1725. Returns:
  1726. TRUE: We are willing to drop a link from the bundle
  1727. FALSE: We need all the links in the bundle
  1728. Description:
  1729. Considers the bandwidth utilization on the bundle represented by pBcbLocal
  1730. and says whether the BAP policy allows us to drop a link.
  1731. When the server receives a drop request, it will always ACK.
  1732. When a client receives a drop request, it will ACK if the utilization is
  1733. less than the lower threshold for the sample period. Otherwise, it will NAK.
  1734. */
  1735. BOOL
  1736. FOkToDropLink(
  1737. IN BCB * pBcbLocal,
  1738. IN BAPCB * pBapCbRemote
  1739. )
  1740. {
  1741. PCB* pPcbLocal;
  1742. RAS_GET_BANDWIDTH_UTILIZATION Util;
  1743. DWORD dwLowThreshold;
  1744. DWORD dwUpPeriod;
  1745. DWORD dwDownPeriod;
  1746. DWORD dwErr;
  1747. if (pBcbLocal->fFlags & BCBFLAG_IS_SERVER)
  1748. {
  1749. return(TRUE);
  1750. }
  1751. pPcbLocal = GetPCBPointerFromBCB(pBcbLocal);
  1752. if (NULL == pPcbLocal)
  1753. {
  1754. BapTrace("FOkToAddLink: No links in HCONN 0x%x!",
  1755. pBcbLocal->hConnection);
  1756. return(FALSE);
  1757. }
  1758. dwErr = RasGetBandwidthUtilization(pPcbLocal->hPort, &Util);
  1759. if (NO_ERROR != dwErr)
  1760. {
  1761. BapTrace("RasGetBandwidthUtilization failed and returned %d", dwErr);
  1762. return(FALSE);
  1763. }
  1764. dwDownPeriod = pBcbLocal->BapParams.dwHangUpExtraSampleSeconds;
  1765. dwUpPeriod = pBcbLocal->BapParams.dwDialExtraSampleSeconds;
  1766. BapTrace("Utilization: "
  1767. "%d sec: (Xmit: %d%%, Recv: %d%%), "
  1768. "%d sec: (Xmit: %d%%, Recv: %d%%)",
  1769. dwUpPeriod, Util.ulUpperXmitUtil, Util.ulUpperRecvUtil,
  1770. dwDownPeriod, Util.ulLowerXmitUtil, Util.ulLowerRecvUtil);
  1771. dwLowThreshold = pBcbLocal->BapParams.dwHangUpExtraPercent;
  1772. if ( (Util.ulLowerXmitUtil < dwLowThreshold)
  1773. && (Util.ulLowerRecvUtil < dwLowThreshold))
  1774. {
  1775. return(TRUE);
  1776. }
  1777. return(FALSE);
  1778. }
  1779. /*
  1780. Returns:
  1781. TRUE: Upper limit reached
  1782. FALSE: Upper limit not reached
  1783. Description:
  1784. Returns TRUE iff we can add another link to the multilink bundle
  1785. represented by pBclLocal. This function is used to Full-Nak a
  1786. Call[back]-Request.
  1787. */
  1788. BOOL
  1789. FUpperLimitReached(
  1790. IN BCB * pBcbLocal
  1791. )
  1792. {
  1793. if (NumLinksInBundle(pBcbLocal) >= pBcbLocal->dwMaxLinksAllowed)
  1794. {
  1795. return(TRUE);
  1796. }
  1797. return(FALSE);
  1798. }
  1799. /*
  1800. Returns:
  1801. TRUE: Success
  1802. FALSE: Failure
  1803. Description:
  1804. Fills in some of the fields of pBcbLocal->BapCb (our BapCb) by considering
  1805. pBapCbRemote (the BapCb sent by the peer). dwPacketType is the type of
  1806. packet that we want to send.
  1807. For all packet types:
  1808. dwType = dwPacketType
  1809. dwOptions = the options (see BAP_N_*), whose values have been set
  1810. BAP_PACKET_CALL_REQ:
  1811. dwLinkType, dwLinkSpeed
  1812. BAP_PACKET_CALL_RESP:
  1813. dwLink-Type+, pbPhoneDelta+
  1814. BAP_PACKET_CALLBACK_REQ:
  1815. dwLinkType, dwLinkSpeed, pbPhoneDelta
  1816. BAP_PACKET_CALLBACK_RESP:
  1817. dwLink-Type+
  1818. BAP_PACKET_DROP_REQ:
  1819. dwLinkDiscriminator
  1820. + indicates that the field may not be filled in.
  1821. */
  1822. BOOL
  1823. FFillBapCb(
  1824. IN DWORD dwPacketType,
  1825. OUT BCB* pBcbLocal,
  1826. IN BAPCB* pBapCbRemote
  1827. )
  1828. {
  1829. DWORD dwOptions = 0;
  1830. BOOL fResult = TRUE;
  1831. BOOL fServer;
  1832. BOOL fRouter;
  1833. PCB* pPcbLocal;
  1834. LCPCB* pLcpCb;
  1835. BAPCB* pBapCbLocal;
  1836. BOOL fCall;
  1837. BOOL fGetOurPhoneNumber;
  1838. DWORD dwLength;
  1839. PPP_ASSERT(NULL != pBcbLocal);
  1840. pBapCbLocal = &(pBcbLocal->BapCb);
  1841. PPP_ASSERT(BAP_STATE_INITIAL == pBapCbLocal->BapState);
  1842. if (((BAP_PACKET_CALL_REQ == dwPacketType) &&
  1843. (pBcbLocal->fFlags & BCBFLAG_PEER_CANT_ACCEPT_CALLS)) ||
  1844. ((BAP_PACKET_CALLBACK_REQ == dwPacketType) &&
  1845. (pBcbLocal->fFlags & BCBFLAG_PEER_CANT_CALL)))
  1846. {
  1847. BapTrace("FFillBapCb: Peer rejects %s",
  1848. BAP_PACKET_CALL_REQ == dwPacketType ? "Call-Requests" :
  1849. "Callback-Requests");
  1850. fResult = FALSE;
  1851. goto LDone;
  1852. }
  1853. pPcbLocal = GetPCBPointerFromBCB(pBcbLocal);
  1854. if (NULL == pPcbLocal)
  1855. {
  1856. BapTrace("FFillBapCb: No links in HCONN 0x%x!", pBcbLocal->hConnection);
  1857. fResult = FALSE;
  1858. goto LDone;
  1859. }
  1860. fServer = (pBcbLocal->fFlags & BCBFLAG_IS_SERVER) != 0;
  1861. fRouter =
  1862. (ROUTER_IF_TYPE_FULL_ROUTER == pBcbLocal->InterfaceInfo.IfType);
  1863. if (dwPacketType == BAP_PACKET_CALL_REQ ||
  1864. dwPacketType == BAP_PACKET_CALLBACK_REQ ||
  1865. dwPacketType == BAP_PACKET_CALL_RESP ||
  1866. dwPacketType == BAP_PACKET_CALLBACK_RESP)
  1867. {
  1868. if (FUpperLimitReached(pBcbLocal))
  1869. {
  1870. BapTrace("FFillBapCb: Link limit reached on HCONN 0x%x: %d",
  1871. pBcbLocal->hConnection,
  1872. pBcbLocal->dwMaxLinksAllowed);
  1873. fResult = FALSE;
  1874. goto LDone;
  1875. }
  1876. }
  1877. switch(dwPacketType)
  1878. {
  1879. case BAP_PACKET_CALL_REQ:
  1880. case BAP_PACKET_CALLBACK_REQ:
  1881. PPP_ASSERT(!fServer);
  1882. fCall = (BAP_PACKET_CALL_REQ == dwPacketType);
  1883. if (pBapCbRemote != NULL)
  1884. {
  1885. // The peer NAK'ed our Call-Request or Callback-Request and
  1886. // specified a different link type in the NAK.
  1887. pBapCbLocal->dwLinkType = pBapCbRemote->dwLinkType;
  1888. pBapCbLocal->dwLinkSpeed = pBapCbRemote->dwLinkSpeed;
  1889. }
  1890. else
  1891. {
  1892. // We don't have any link type preference
  1893. pBapCbLocal->dwLinkType = 0;
  1894. }
  1895. if (!FGetAvailableLinkClientOrRouter(
  1896. pPcbLocal,
  1897. pBcbLocal->szPhonebookPath,
  1898. pBcbLocal->szEntryName,
  1899. fCall,
  1900. fRouter,
  1901. pBcbLocal->szTextualSid,
  1902. &(pBapCbLocal->dwLinkType),
  1903. &(pBapCbLocal->dwLinkSpeed),
  1904. fCall ? pBapCbLocal->szPeerPhoneNumber : NULL,
  1905. &(pBapCbLocal->dwSubEntryIndex),
  1906. fCall ? NULL : pBapCbLocal->pbPhoneDelta,
  1907. fCall ? NULL : pBapCbLocal->szPortName,
  1908. NULL /* szBasePhoneNumber */))
  1909. {
  1910. BapTrace("FFillBapCb: Requested link type not available");
  1911. fResult = FALSE;
  1912. goto LDone;
  1913. }
  1914. dwOptions = BAP_N_LINK_TYPE;
  1915. if (fCall)
  1916. {
  1917. if (pBapCbLocal->szPeerPhoneNumber[0])
  1918. {
  1919. dwOptions |= BAP_N_NO_PH_NEEDED;
  1920. }
  1921. }
  1922. else
  1923. {
  1924. // If we ask for our phone number, FGetAvailableLinkClientOrRouter()
  1925. // must provide it or return FALSE
  1926. PPP_ASSERT(pBapCbLocal->pbPhoneDelta[0]);
  1927. dwOptions |= BAP_N_PHONE_DELTA;
  1928. }
  1929. break;
  1930. case BAP_PACKET_CALL_RESP:
  1931. case BAP_PACKET_CALLBACK_RESP:
  1932. PPP_ASSERT(NULL != pBapCbRemote);
  1933. fCall = (BAP_PACKET_CALL_RESP == dwPacketType);
  1934. // We need to send our phone number to the peer if we are responding to
  1935. // a Call-Request and the peer has not sent the No-Phone-Number-Needed
  1936. // option.
  1937. fGetOurPhoneNumber = fCall &&
  1938. !(pBapCbRemote->dwOptions & BAP_N_NO_PH_NEEDED);
  1939. // Case nRS: fServer && !fRouter (Non-Router Servers)
  1940. // Case CR: !fServer || fRouter (Clients and Routers)
  1941. // Case SR: fServer || fRouter (Servers and Routers)
  1942. if (FGetAvailableLink(
  1943. pPcbLocal,
  1944. fServer,
  1945. fRouter,
  1946. !fCall,
  1947. pBcbLocal->szPhonebookPath, // Meaningless in Case nRS
  1948. pBcbLocal->szEntryName, // Meaningless in Case nRS
  1949. pBcbLocal->szTextualSid, // Meaningless in Case SR
  1950. &(pBapCbRemote->dwLinkType),
  1951. &(pBapCbRemote->dwLinkSpeed),
  1952. pBapCbLocal->szPeerPhoneNumber, // Meaningless in Case nRS
  1953. &(pBapCbLocal->dwSubEntryIndex),// Meaningless in Case nRS
  1954. &(pBapCbLocal->hPort), // Meaningless in Case CR
  1955. fGetOurPhoneNumber ? pBapCbLocal->pbPhoneDelta : NULL,
  1956. // Meaningless in Case SR
  1957. fCall ? pBapCbLocal->szPortName : NULL,
  1958. fGetOurPhoneNumber && fServer ?
  1959. pBapCbLocal->szServerPhoneNumber : NULL))
  1960. {
  1961. if (fGetOurPhoneNumber)
  1962. {
  1963. // If we ask for our phone number, FGetAvailableLink()
  1964. // must provide it or return FALSE
  1965. PPP_ASSERT(pBapCbLocal->pbPhoneDelta[0]);
  1966. dwOptions = BAP_N_PHONE_DELTA;
  1967. }
  1968. }
  1969. else
  1970. {
  1971. // We don't have the link type requested. Fill BapCb with
  1972. // details of a link type that we do have.
  1973. BapTrace("FFillBapCb: Requested link type not available. "
  1974. "Let us tell the peer what we have.");
  1975. fResult = FALSE;
  1976. // If fGetOurPhoneNumber, assume that the peer doesn't have any
  1977. // phone number. So send him a new link type only if we have its
  1978. // phone number.
  1979. // We don't have any link type preference
  1980. pBapCbLocal->dwLinkType = 0;
  1981. if (FGetAvailableLink(
  1982. pPcbLocal,
  1983. fServer,
  1984. fRouter,
  1985. !fCall,
  1986. pBcbLocal->szPhonebookPath, // Meaningless in Case nRS
  1987. pBcbLocal->szEntryName, // Meaningless in Case nRS
  1988. pBcbLocal->szTextualSid, // Meaningless in Case SR
  1989. &(pBapCbLocal->dwLinkType),
  1990. &(pBapCbLocal->dwLinkSpeed),
  1991. NULL /* szPeerPhoneNumber */,
  1992. NULL /* pdwSubEntryIndex */,
  1993. NULL /* phPort */,
  1994. NULL /* pbPhoneDelta */,
  1995. NULL /* szPortName */,
  1996. NULL /* szBasePhoneNumber */))
  1997. {
  1998. dwOptions = BAP_N_LINK_TYPE;
  1999. }
  2000. }
  2001. break;
  2002. case BAP_PACKET_DROP_REQ:
  2003. if (NumLinksInBundle(pBcbLocal) <= 1)
  2004. {
  2005. BapTrace("FFillBapCb: Only one link in the bundle");
  2006. fResult = FALSE;
  2007. }
  2008. else
  2009. {
  2010. // This will cause the link represented by pPcbLocal to get dropped.
  2011. // This link happens to have the highest dwSubEntryIndex, so we are
  2012. // happy.
  2013. pLcpCb = (LCPCB*)(pPcbLocal->LcpCb.pWorkBuf);
  2014. PPP_ASSERT(pLcpCb->Remote.Work.dwLinkDiscriminator <= 0xFFFF);
  2015. pBapCbLocal->dwLinkDiscriminator =
  2016. pLcpCb->Remote.Work.dwLinkDiscriminator;
  2017. dwOptions = BAP_N_LINK_DISC;
  2018. }
  2019. break;
  2020. }
  2021. LDone:
  2022. pBapCbLocal->dwType = dwPacketType;
  2023. pBapCbLocal->dwOptions = dwOptions;
  2024. return(fResult);
  2025. }
  2026. /*
  2027. Returns:
  2028. void
  2029. Description:
  2030. This function asks NdisWan to inform us if the bandwidth utilization for
  2031. the bundle represented by pBcb goes out of the desired range for a given
  2032. amount of time.
  2033. */
  2034. VOID
  2035. BapSetPolicy(
  2036. IN BCB * pBcb
  2037. )
  2038. {
  2039. DWORD dwLowThreshold;
  2040. DWORD dwHighThreshold;
  2041. DWORD dwLowSamplePeriod;
  2042. DWORD dwHighSamplePeriod;
  2043. DWORD dwErr;
  2044. PPP_ASSERT(NULL != pBcb);
  2045. dwLowThreshold = pBcb->BapParams.dwHangUpExtraPercent;
  2046. dwLowSamplePeriod = pBcb->BapParams.dwHangUpExtraSampleSeconds;
  2047. dwHighThreshold = pBcb->BapParams.dwDialExtraPercent;
  2048. dwHighSamplePeriod = pBcb->BapParams.dwDialExtraSampleSeconds;
  2049. dwErr = RasSetBapPolicy(pBcb->hConnection,
  2050. dwLowThreshold, dwLowSamplePeriod,
  2051. dwHighThreshold, dwHighSamplePeriod);
  2052. if (NO_ERROR != dwErr)
  2053. {
  2054. BapTrace("RasPppSetBapPolicy returned error %d", dwErr);
  2055. return;
  2056. }
  2057. BapTrace("BapSetPolicy on HCONN 0x%x: Low: %d%% for %d sec; "
  2058. "High: %d%% for %d sec",
  2059. pBcb->hConnection,
  2060. dwLowThreshold, dwLowSamplePeriod,
  2061. dwHighThreshold, dwHighSamplePeriod);
  2062. }
  2063. /*
  2064. Returns:
  2065. void
  2066. Description:
  2067. Increments dwId in pBcb->BapCb.
  2068. */
  2069. VOID
  2070. IncrementId(
  2071. IN BCB* pBcb
  2072. )
  2073. {
  2074. DWORD* pdwLastId;
  2075. BYTE bId;
  2076. pdwLastId = &(pBcb->BapCb.dwId);
  2077. bId = (BYTE)(*pdwLastId);
  2078. // 0 -> FF -> 0 -> ...
  2079. bId++;
  2080. *pdwLastId = bId;
  2081. }
  2082. /*
  2083. Returns:
  2084. void
  2085. Description:
  2086. Used for displaying BAP packets. fReceived is TRUE iff the packet was
  2087. received from the peer. hPort represents the port on which the packet was
  2088. sent/received. pBcb represents the bundle that owns this packet. pPacket
  2089. points to the packet that was sent/received and cbPacket is the number of
  2090. bytes in the packet.
  2091. */
  2092. VOID
  2093. LogBapPacket(
  2094. IN BOOL fReceived,
  2095. IN HPORT hPort,
  2096. IN BCB* pBcb,
  2097. IN PPP_PACKET* pPacket,
  2098. IN DWORD cbPacket
  2099. )
  2100. {
  2101. BAP_RESPONSE* pBapResponse;
  2102. DWORD dwType;
  2103. static CHAR* szBapResponseName[] =
  2104. {
  2105. "ACK",
  2106. "NAK",
  2107. "REJ",
  2108. "FULL-NAK"
  2109. };
  2110. PPP_ASSERT(NULL != pBcb);
  2111. PPP_ASSERT(NULL != pPacket);
  2112. pBapResponse = (BAP_RESPONSE *)(pPacket->Information);
  2113. dwType = pBapResponse->Type;
  2114. BapTrace(" ");
  2115. BapTrace("Number of links in HCONN 0x%x: %d", pBcb->hConnection,
  2116. NumLinksInBundle(pBcb));
  2117. BapTrace("%sBAP packet %s:",
  2118. fReceived ? ">" : "<", fReceived ? "received" : "sent");
  2119. BapTrace("%sType: %s, Length: %d, Id: 0x%x, HCONN: 0x%x, hPort: %d%s",
  2120. fReceived ? ">" : "<",
  2121. dwType <= BAP_PACKET_LIMIT ?
  2122. SzBapPacketName[dwType] : "UNKNOWN",
  2123. cbPacket, pBapResponse->Id,
  2124. pBcb->hConnection, hPort,
  2125. hPort == (HPORT) -1 ? " (not known)" : "");
  2126. TraceDumpExA(DwBapTraceId,
  2127. 0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC,
  2128. (CHAR*)pPacket,
  2129. cbPacket,
  2130. 1,
  2131. FALSE,
  2132. fReceived ? ">" : "<");
  2133. if (((dwType == BAP_PACKET_CALL_RESP) ||
  2134. (dwType == BAP_PACKET_CALLBACK_RESP) ||
  2135. (dwType == BAP_PACKET_DROP_RESP)) &&
  2136. pBapResponse->ResponseCode <= BAP_RESPONSE_FULL_NAK)
  2137. {
  2138. BapTrace("%sResponse Code: %s", fReceived ? ">" : "<",
  2139. szBapResponseName[pBapResponse->ResponseCode]);
  2140. }
  2141. BapTrace(" ");
  2142. }
  2143. /*
  2144. Returns:
  2145. TRUE: Favored-Peer
  2146. FALSE: not Favored-Peer
  2147. Description:
  2148. Returns TRUE iff the peer represented by pBcb is the favored peer.
  2149. */
  2150. BOOL
  2151. FFavoredPeer(
  2152. IN BCB* pBcb
  2153. )
  2154. {
  2155. DWORD dwCpIndex;
  2156. CPCB* pCpCb;
  2157. BACPCB* pBacpCb;
  2158. PCB* pPcb;
  2159. dwCpIndex = GetCpIndexFromProtocol(PPP_BACP_PROTOCOL);
  2160. PPP_ASSERT((DWORD)-1 != dwCpIndex);
  2161. PPP_ASSERT(NULL != pBcb);
  2162. pPcb = GetPCBPointerFromBCB(pBcb);
  2163. if (NULL == pPcb)
  2164. {
  2165. BapTrace("FFavoredPeer: No links in HCONN 0x%x!", pBcb->hConnection);
  2166. return(TRUE);
  2167. }
  2168. if (dwCpIndex != (DWORD)-1)
  2169. {
  2170. pCpCb = GetPointerToCPCB(pPcb, dwCpIndex);
  2171. PPP_ASSERT(NULL != pCpCb);
  2172. if (NULL != pCpCb)
  2173. {
  2174. pBacpCb = (BACPCB *)(pCpCb->pWorkBuf);
  2175. /*
  2176. The favored peer is the peer that transmits the lowest Magic-Number
  2177. in its Favored-Peer Configuration Option.
  2178. */
  2179. return(pBacpCb->dwLocalMagicNumber < pBacpCb->dwRemoteMagicNumber);
  2180. }
  2181. }
  2182. return(TRUE);
  2183. }
  2184. /*
  2185. Returns:
  2186. TRUE: Success
  2187. FALSE: Failure
  2188. Description:
  2189. Looks in the bundle represented by pBcb, for a link whose Link
  2190. Discriminator = dwLinkDiscriminator. If fRemote, the remote Link
  2191. Discriminator is used. Else the local one is used. Returns the pPcb of the
  2192. link in ppPcb.
  2193. */
  2194. BOOL
  2195. FGetPcbOfLink(
  2196. IN BCB* pBcb,
  2197. IN DWORD dwLinkDiscriminator,
  2198. IN BOOL fRemote,
  2199. OUT PCB** ppPcb
  2200. )
  2201. {
  2202. DWORD dwForIndex;
  2203. LCPCB* pLcpCb;
  2204. PPP_ASSERT(NULL != pBcb);
  2205. PPP_ASSERT(0xFFFF >= dwLinkDiscriminator);
  2206. PPP_ASSERT(NULL != ppPcb);
  2207. for (dwForIndex = 0; dwForIndex < pBcb->dwPpcbArraySize; dwForIndex++)
  2208. {
  2209. // Look at all the ports in the bundle for the port with the right Link
  2210. // Discriminator.
  2211. *ppPcb = pBcb->ppPcb[dwForIndex];
  2212. if (*ppPcb != NULL)
  2213. {
  2214. pLcpCb = (LCPCB*)((*ppPcb)->LcpCb.pWorkBuf);
  2215. PPP_ASSERT(NULL != pLcpCb);
  2216. if (fRemote)
  2217. {
  2218. PPP_ASSERT(pLcpCb->Remote.Work.dwLinkDiscriminator <= 0xFFFF);
  2219. if (pLcpCb->Remote.Work.dwLinkDiscriminator ==
  2220. dwLinkDiscriminator)
  2221. {
  2222. return(TRUE);
  2223. }
  2224. }
  2225. else
  2226. {
  2227. PPP_ASSERT(pLcpCb->Local.Work.dwLinkDiscriminator <= 0xFFFF);
  2228. if (pLcpCb->Local.Work.dwLinkDiscriminator ==
  2229. dwLinkDiscriminator)
  2230. {
  2231. return(TRUE);
  2232. }
  2233. }
  2234. }
  2235. }
  2236. BapTrace("FGetPcbOfLink: There is no link in HCONN 0x%x, whose remote "
  2237. "Link Disc is %d",
  2238. pBcb->hConnection, dwLinkDiscriminator);
  2239. *ppPcb = NULL;
  2240. return(FALSE);
  2241. }
  2242. /*
  2243. Returns:
  2244. TRUE: Success
  2245. FALSE: Failure
  2246. Description:
  2247. Scans the BAP Datagram Options in the PPP packet pPacket. dwPacketType is
  2248. the BAP Datagram Type (see BAP_PACKET_*). dwLength is the BAP Datagram
  2249. Length. pBapCbRemote (including dwType and dwOptions) is filled up using
  2250. these options.
  2251. */
  2252. BOOL
  2253. FReadOptions(
  2254. IN PPP_PACKET* pPacket,
  2255. IN DWORD dwPacketType,
  2256. IN DWORD dwLength,
  2257. OUT BAPCB* pBapCbRemote
  2258. )
  2259. {
  2260. PPP_OPTION* pOption;
  2261. BYTE* pbData;
  2262. DWORD dwIndex = 0;
  2263. DWORD dwUniqueDigits;
  2264. DWORD dwSubscribNumLength;
  2265. BYTE* pbNumberOption;
  2266. BYTE* pbSubAddrOption;
  2267. DWORD dwPhoneDeltaLength;
  2268. PPP_ASSERT(NULL != pPacket);
  2269. PPP_ASSERT(NULL != pBapCbRemote);
  2270. if (dwPacketType > BAP_PACKET_LIMIT)
  2271. {
  2272. BapTrace("Unknown BAP Datagram Type: %d", dwPacketType);
  2273. return(FALSE);
  2274. }
  2275. if (dwPacketType == BAP_PACKET_CALL_RESP ||
  2276. dwPacketType == BAP_PACKET_CALLBACK_RESP ||
  2277. dwPacketType == BAP_PACKET_DROP_RESP ||
  2278. dwPacketType == BAP_PACKET_STAT_RESP)
  2279. {
  2280. if (BAP_RESPONSE_HDR_LEN > dwLength)
  2281. {
  2282. return(FALSE);
  2283. }
  2284. pOption = (PPP_OPTION *)(pPacket->Information + BAP_RESPONSE_HDR_LEN);
  2285. dwLength -= BAP_RESPONSE_HDR_LEN;
  2286. }
  2287. else
  2288. {
  2289. if (PPP_CONFIG_HDR_LEN > dwLength)
  2290. {
  2291. return(FALSE);
  2292. }
  2293. pOption = (PPP_OPTION *)(pPacket->Information + PPP_CONFIG_HDR_LEN);
  2294. dwLength -= PPP_CONFIG_HDR_LEN;
  2295. }
  2296. ZeroMemory(pBapCbRemote, sizeof(BAPCB));
  2297. pBapCbRemote->dwType = dwPacketType;
  2298. while(dwLength > 0)
  2299. {
  2300. if (0 == pOption->Length || dwLength < pOption->Length)
  2301. {
  2302. BapTrace("FReadOptions: Invalid BAP Datagram Length");
  2303. return(FALSE);
  2304. }
  2305. dwLength -= pOption->Length;
  2306. if (pOption->Type <= BAP_OPTION_LIMIT)
  2307. {
  2308. pBapCbRemote->dwOptions |= (1 << pOption->Type);
  2309. }
  2310. switch(pOption->Type)
  2311. {
  2312. case BAP_OPTION_LINK_TYPE:
  2313. if (pOption->Length != PPP_OPTION_HDR_LEN + 3)
  2314. {
  2315. BapTrace("FReadOptions: Invalid length for Link-Type: %d",
  2316. pOption->Length);
  2317. return(FALSE);
  2318. }
  2319. pBapCbRemote->dwLinkSpeed = WireToHostFormat16(pOption->Data);
  2320. pBapCbRemote->dwLinkType = pOption->Data[2];
  2321. if (0 == pBapCbRemote->dwLinkType)
  2322. {
  2323. // In FGetAvailableLink(), we interpret Link Type 0 to
  2324. // mean "any link"
  2325. BapTrace("FReadOptions: Invalid Link-Type: 0");
  2326. return(FALSE);
  2327. }
  2328. break;
  2329. case BAP_OPTION_PHONE_DELTA:
  2330. /*
  2331. An implementation MAY include more than one Phone-Delta option in a
  2332. response.
  2333. dwIndex is the index into pBapCbRemote->pbPhoneDelta where we should
  2334. start writing.
  2335. If the only Sub-Options are Unique-Digits and Subscriber-Number,
  2336. the number of bytes we want to store is pOption->Length - 3.
  2337. Eg, if we get
  2338. 02 11 (01 3 4) (02 6 9 9 9 9)
  2339. we store
  2340. 4 0 9 9 9 9 0 0, ie 11 - 3 = 8 bytes
  2341. If Phone-Number-Sub-Address is also present, we will need
  2342. pOption->Length - 5 bytes in pBapCbRemote->pbPhoneDelta.
  2343. Eg, if we get
  2344. 02 15 (01 3 4) (02 6 9 9 9 9) (03 4 9 9)
  2345. we store
  2346. 4 0 9 9 9 9 0 9 9 0, ie 15 - 5 = 10 bytes
  2347. pbPhoneDelta has BAP_PHONE_DELTA_SIZE + 1 bytes, and we put the
  2348. terminating 0 byte after we have read all the Options.
  2349. */
  2350. if (dwIndex + pOption->Length - 3 <= BAP_PHONE_DELTA_SIZE)
  2351. {
  2352. // Read the Phone-Delta option
  2353. pbData = pOption->Data;
  2354. dwPhoneDeltaLength = pOption->Length - PPP_OPTION_HDR_LEN;
  2355. dwUniqueDigits = 0;
  2356. pbNumberOption = pbSubAddrOption = NULL;
  2357. while(dwPhoneDeltaLength > 0)
  2358. {
  2359. /*
  2360. Read the Sub-Options.
  2361. If there are multiple Sub-Options of the same type (which
  2362. shouldn't really happen), we remember only the last
  2363. Sub-Option of each type.
  2364. */
  2365. // pbData[1] contains Sub-Option Length
  2366. if (2 > pbData[1] || dwPhoneDeltaLength < pbData[1])
  2367. {
  2368. BapTrace("FReadOptions: Invalid BAP Datagram "
  2369. "Sub-Option Length");
  2370. return(FALSE);
  2371. }
  2372. dwPhoneDeltaLength -= pbData[1];
  2373. // pbData[0] contains Sub-Option Type
  2374. switch(pbData[0])
  2375. {
  2376. case BAP_SUB_OPTION_UNIQUE_DIGITS:
  2377. if (pbData[1] != 3)
  2378. {
  2379. BapTrace("FReadOptions: Invalid length for "
  2380. "Unique-Digits: %d",
  2381. pbData[1]);
  2382. return(FALSE);
  2383. }
  2384. dwUniqueDigits = pbData[2];
  2385. break;
  2386. case BAP_SUB_OPTION_SUBSCRIB_NUM:
  2387. dwSubscribNumLength = pbData[1] - 2;
  2388. if (dwSubscribNumLength > MAX_PHONE_NUMBER_LEN)
  2389. {
  2390. BapTrace("FReadOptions: Subscriber-Number too "
  2391. "long: %d",
  2392. pbData[1] - 2);
  2393. return(FALSE);
  2394. }
  2395. pbNumberOption = pbData;
  2396. if (!FAsciiDigits(pbNumberOption + 2,
  2397. dwSubscribNumLength))
  2398. {
  2399. BapTrace("FReadOptions: Subscriber-Number contains "
  2400. "bytes other than ASCII digits");
  2401. return(FALSE);
  2402. }
  2403. break;
  2404. case BAP_SUB_OPTION_SUB_ADDR:
  2405. if (pbData[1] - 2 > MAX_PHONE_NUMBER_LEN)
  2406. {
  2407. BapTrace("FReadOptions: Phone-Number-Sub-Address "
  2408. "too long: %d",
  2409. pbData[1] - 2);
  2410. return(FALSE);
  2411. }
  2412. pbSubAddrOption = pbData;
  2413. if (!FAsciiDigits(pbSubAddrOption + 2,
  2414. pbSubAddrOption[1] - 2))
  2415. {
  2416. BapTrace("FReadOptions: Phone-Number-Sub-Address "
  2417. "contains bytes other than ASCII digits");
  2418. return(FALSE);
  2419. }
  2420. break;
  2421. default:
  2422. BapTrace("FReadOptions: Unknown Phone-Delta Sub-Option "
  2423. "Type %d",
  2424. pbData[0]);
  2425. break;
  2426. }
  2427. pbData += pbData[1];
  2428. }
  2429. if (pbNumberOption == NULL ||
  2430. dwUniqueDigits > dwSubscribNumLength)
  2431. {
  2432. BapTrace("FReadOptions: Invalid Unique-Digits or "
  2433. "Subscriber-Number in Phone-Delta");
  2434. return(FALSE);
  2435. }
  2436. if (0 == dwUniqueDigits)
  2437. {
  2438. // We cannot write 0 0 0. See BAPCB comments
  2439. pBapCbRemote->pbPhoneDelta[dwIndex++] = 0xFF;
  2440. }
  2441. else
  2442. {
  2443. pBapCbRemote->pbPhoneDelta[dwIndex++] = (BYTE)dwUniqueDigits;
  2444. pBapCbRemote->pbPhoneDelta[dwIndex++] = 0;
  2445. CopyMemory(pBapCbRemote->pbPhoneDelta + dwIndex,
  2446. pbNumberOption + 2 + dwSubscribNumLength - dwUniqueDigits,
  2447. dwSubscribNumLength);
  2448. dwIndex += pbNumberOption[1] - 2;
  2449. pBapCbRemote->pbPhoneDelta[dwIndex++] = 0;
  2450. if (pbSubAddrOption != NULL)
  2451. {
  2452. CopyMemory(pBapCbRemote->pbPhoneDelta + dwIndex,
  2453. pbSubAddrOption + 2, pbSubAddrOption[1] - 2);
  2454. dwIndex += pbSubAddrOption[1] - 2;
  2455. }
  2456. pBapCbRemote->pbPhoneDelta[dwIndex++] = 0;
  2457. }
  2458. }
  2459. else if (dwIndex == 0)
  2460. {
  2461. // We were unable to read any Phone-Deltas
  2462. BapTrace("FReadOptions: Couldn't read any Phone-Delta");
  2463. return(FALSE);
  2464. }
  2465. break;
  2466. case BAP_OPTION_NO_PH_NEEDED:
  2467. if (pOption->Length != PPP_OPTION_HDR_LEN)
  2468. {
  2469. BapTrace("FReadOptions: Invalid length for "
  2470. "No-Phone-Number-Needed: %d",
  2471. pOption->Length);
  2472. return(FALSE);
  2473. }
  2474. // In pBapCbRemote->dwOptions, we remember that we have seen this
  2475. // option. We don't need to do anything else.
  2476. break;
  2477. case BAP_OPTION_REASON:
  2478. break;
  2479. case BAP_OPTION_LINK_DISC:
  2480. if (pOption->Length != PPP_OPTION_HDR_LEN + 2)
  2481. {
  2482. BapTrace("FReadOptions: Invalid length for "
  2483. "Link-Discriminator: %d",
  2484. pOption->Length);
  2485. return(FALSE);
  2486. }
  2487. pBapCbRemote->dwLinkDiscriminator
  2488. = WireToHostFormat16(pOption->Data);
  2489. break;
  2490. case BAP_OPTION_CALL_STATUS:
  2491. if (pOption->Length != PPP_OPTION_HDR_LEN + 2)
  2492. {
  2493. BapTrace("FReadOptions: Invalid length for Call-Status: %d",
  2494. pOption->Length);
  2495. return(FALSE);
  2496. }
  2497. pBapCbRemote->dwStatus = pOption->Data[0];
  2498. pBapCbRemote->dwAction = pOption->Data[1];
  2499. break;
  2500. default:
  2501. // Perhaps this is a new option that we don't recognize
  2502. BapTrace("FReadOptions: Unknown BAP Datagram Option: 0x%x",
  2503. pOption->Type);
  2504. break;
  2505. }
  2506. pOption = (PPP_OPTION *)((BYTE*)pOption + pOption->Length);
  2507. }
  2508. // The terminating 0 byte in pbPhoneDelta.
  2509. PPP_ASSERT(dwIndex <= BAP_PHONE_DELTA_SIZE + 1);
  2510. pBapCbRemote->pbPhoneDelta[dwIndex++] = 0;
  2511. if (g_dwMandatoryOptions[dwPacketType] & ~pBapCbRemote->dwOptions)
  2512. {
  2513. BapTrace("FReadOptions: Missing options: Scanned options: 0x%x, "
  2514. "Mandatory options: 0x%x",
  2515. pBapCbRemote->dwOptions, g_dwMandatoryOptions[dwPacketType]);
  2516. return(FALSE);
  2517. }
  2518. else
  2519. {
  2520. return(TRUE);
  2521. }
  2522. }
  2523. /*
  2524. Returns:
  2525. TRUE: Success
  2526. FALSE: Failure
  2527. Description:
  2528. Writes one (or more in the case of Phone-Delta) BAP Datagram Option of type
  2529. dwOptionType (see BAP_OPTION_*) into **ppOption, by looking at the fields
  2530. in pBapCbLocal. *ppOption is updated to point to the place where the next
  2531. option should go. *pcbOption contains the number of free bytes in
  2532. *ppOption. It is decreased by the number of free bytes used up. *ppOption
  2533. and *pcbOption are not modified if the function returns FALSE.
  2534. */
  2535. BOOL
  2536. FMakeBapOption(
  2537. IN BAPCB* pBapCbLocal,
  2538. IN DWORD dwOptionType,
  2539. IN PPP_OPTION** ppOption,
  2540. IN OUT DWORD* pcbOption
  2541. )
  2542. {
  2543. DWORD dwLength;
  2544. DWORD dwNumberOptionSize;
  2545. DWORD dwSubAddrOptionSize;
  2546. BYTE* pbData;
  2547. DWORD dwIndex;
  2548. DWORD dwTempIndex;
  2549. DWORD dwSubAddrIndex;
  2550. DWORD fAtLeastOnePhoneDelta = FALSE;
  2551. PPP_OPTION* pOption;
  2552. PPP_ASSERT(NULL != pBapCbLocal);
  2553. PPP_ASSERT(NULL != ppOption);
  2554. PPP_ASSERT(NULL != pcbOption);
  2555. pOption = *ppOption;
  2556. PPP_ASSERT(NULL != pOption);
  2557. switch(dwOptionType)
  2558. {
  2559. case BAP_OPTION_LINK_TYPE:
  2560. dwLength = PPP_OPTION_HDR_LEN + 3;
  2561. if (*pcbOption < dwLength)
  2562. {
  2563. BapTrace("FMakeBapOption: Buffer too small for Link-Type. "
  2564. "Size: %d, Reqd: %d",
  2565. *pcbOption, dwLength);
  2566. return(FALSE);
  2567. }
  2568. pOption->Length = (BYTE)dwLength;
  2569. PPP_ASSERT(pBapCbLocal->dwLinkSpeed <= 0xFFFF);
  2570. HostToWireFormat16((WORD)(pBapCbLocal->dwLinkSpeed), pOption->Data);
  2571. PPP_ASSERT(pBapCbLocal->dwLinkType <= 0xFF);
  2572. pOption->Data[2] = (BYTE)(pBapCbLocal->dwLinkType);
  2573. break;
  2574. case BAP_OPTION_PHONE_DELTA:
  2575. dwIndex = 0;
  2576. while (pBapCbLocal->pbPhoneDelta[dwIndex])
  2577. {
  2578. if (0xFF == pBapCbLocal->pbPhoneDelta[dwIndex])
  2579. {
  2580. // Unique-Digits is 0. See BAPCB comments
  2581. dwNumberOptionSize = 2;
  2582. dwSubAddrOptionSize = 0;
  2583. dwTempIndex = dwIndex + 1;
  2584. }
  2585. else
  2586. {
  2587. // Write as many Phone-Delta options as possible
  2588. dwTempIndex = dwIndex + 2;
  2589. dwNumberOptionSize = 0;
  2590. while (pBapCbLocal->pbPhoneDelta[dwTempIndex++])
  2591. {
  2592. dwNumberOptionSize++;
  2593. }
  2594. PPP_ASSERT(dwNumberOptionSize <= MAX_PHONE_NUMBER_LEN);
  2595. // Increase by 2 to accommodate Sub-Option Type and Sub-Option
  2596. // Len
  2597. dwNumberOptionSize += 2;
  2598. dwSubAddrIndex = dwTempIndex;
  2599. dwSubAddrOptionSize = 0;
  2600. while (pBapCbLocal->pbPhoneDelta[dwTempIndex++])
  2601. {
  2602. dwSubAddrOptionSize++;
  2603. }
  2604. PPP_ASSERT(dwSubAddrOptionSize <= MAX_PHONE_NUMBER_LEN);
  2605. if (0 != dwSubAddrOptionSize)
  2606. {
  2607. // Increase by 2 to accommodate Sub-Option Type and
  2608. // Sub-Option Len
  2609. dwSubAddrOptionSize += 2;
  2610. }
  2611. }
  2612. dwLength = PPP_OPTION_HDR_LEN + 3 /* for Unique-Digits */ +
  2613. dwNumberOptionSize + dwSubAddrOptionSize;
  2614. if (*pcbOption < dwLength || 0xFF < dwLength)
  2615. {
  2616. break;
  2617. }
  2618. pOption->Type = (BYTE)dwOptionType;
  2619. pOption->Length = (BYTE)dwLength;
  2620. pbData = pOption->Data;
  2621. pbData[0] = BAP_SUB_OPTION_UNIQUE_DIGITS;
  2622. pbData[1] = 3;
  2623. pbData[2] = pBapCbLocal->pbPhoneDelta[dwIndex];
  2624. if (0xFF == pbData[2])
  2625. {
  2626. // Unique-Digits is 0. See BAPCB comments
  2627. pbData[2] = 0;
  2628. }
  2629. pbData += 3;
  2630. pbData[0] = BAP_SUB_OPTION_SUBSCRIB_NUM;
  2631. PPP_ASSERT(dwNumberOptionSize <= 0xFF);
  2632. pbData[1] = (BYTE)dwNumberOptionSize;
  2633. CopyMemory(pbData + 2, pBapCbLocal->pbPhoneDelta + dwIndex + 2,
  2634. dwNumberOptionSize - 2);
  2635. pbData += dwNumberOptionSize;
  2636. if (0 != dwSubAddrOptionSize)
  2637. {
  2638. pbData[0] = BAP_SUB_OPTION_SUB_ADDR;
  2639. PPP_ASSERT(dwSubAddrOptionSize <= 0xFF);
  2640. pbData[1] = (BYTE)dwSubAddrOptionSize;
  2641. CopyMemory(pbData + 2,
  2642. pBapCbLocal->pbPhoneDelta + dwSubAddrIndex,
  2643. dwSubAddrOptionSize - 2);
  2644. }
  2645. *pcbOption -= dwLength;
  2646. pOption = (PPP_OPTION *)((BYTE *)pOption + dwLength);
  2647. dwIndex = dwTempIndex;
  2648. fAtLeastOnePhoneDelta = TRUE;
  2649. }
  2650. if (!fAtLeastOnePhoneDelta)
  2651. {
  2652. BapTrace("FMakeBapOption: Buffer too small for Phone-Delta. "
  2653. "Size: %d, Reqd: %d",
  2654. *pcbOption, dwLength);
  2655. return(FALSE);
  2656. }
  2657. else
  2658. {
  2659. // We need to return from here. We don't want to set pOption->Type.
  2660. *ppOption = pOption;
  2661. return(TRUE);
  2662. }
  2663. break;
  2664. case BAP_OPTION_NO_PH_NEEDED:
  2665. dwLength = PPP_OPTION_HDR_LEN;
  2666. if (*pcbOption < dwLength)
  2667. {
  2668. BapTrace("FMakeBapOption: Buffer too small for "
  2669. "No-Phone-Number-Needed. Size: %d, Reqd: %d",
  2670. *pcbOption, dwLength);
  2671. return(FALSE);
  2672. }
  2673. pOption->Length = (BYTE)dwLength;
  2674. break;
  2675. case BAP_OPTION_REASON:
  2676. dwLength = PPP_OPTION_HDR_LEN;
  2677. break;
  2678. case BAP_OPTION_LINK_DISC:
  2679. dwLength = PPP_OPTION_HDR_LEN + 2;
  2680. if (*pcbOption < dwLength)
  2681. {
  2682. BapTrace("FMakeBapOption: Buffer too small for Link-Discriminator. "
  2683. "Size: %d, Reqd: %d",
  2684. *pcbOption, dwLength);
  2685. return(FALSE);
  2686. }
  2687. pOption->Length = (BYTE)dwLength;
  2688. PPP_ASSERT(pBapCbLocal->dwLinkDiscriminator <= 0xFFFF);
  2689. HostToWireFormat16((WORD)(pBapCbLocal->dwLinkDiscriminator),
  2690. pOption->Data);
  2691. break;
  2692. case BAP_OPTION_CALL_STATUS:
  2693. dwLength = PPP_OPTION_HDR_LEN + 2;
  2694. if (*pcbOption < dwLength)
  2695. {
  2696. BapTrace("FMakeBapOption: Buffer too small for Call-Status. "
  2697. "Size: %d, Reqd: %d",
  2698. *pcbOption, dwLength);
  2699. return(FALSE);
  2700. }
  2701. pOption->Length = (BYTE)dwLength;
  2702. PPP_ASSERT(pBapCbLocal->dwStatus <= 0xFF);
  2703. pOption->Data[0] = (BYTE)(pBapCbLocal->dwStatus);
  2704. PPP_ASSERT(pBapCbLocal->dwAction <= 0xFF);
  2705. pOption->Data[1] = (BYTE)(pBapCbLocal->dwAction);
  2706. break;
  2707. default:
  2708. BapTrace("FMakeBapOption: Unknown BAP Datagram Option: %d. Ignoring.",
  2709. dwOptionType);
  2710. return(FALSE);
  2711. }
  2712. *ppOption = (PPP_OPTION *)((BYTE *)pOption + dwLength);
  2713. *pcbOption -= dwLength;
  2714. pOption->Type = (BYTE)dwOptionType;
  2715. return(TRUE);
  2716. }
  2717. /*
  2718. Returns:
  2719. TRUE: Success
  2720. FALSE: Failure
  2721. Description:
  2722. Writes BAP Datagram Options specified by dwOptions (see BAP_N_*) into
  2723. pbData, by consulting pBapCbLocal. *pcbOptions contains the number of free
  2724. bytes in pbData. It is decreased by the number of free bytes used up.
  2725. *pcbOptions may be modified even if the function returns FALSE.
  2726. */
  2727. BOOL
  2728. FBuildBapOptionList(
  2729. IN BAPCB* pBapCbLocal,
  2730. IN DWORD dwOptions,
  2731. IN BYTE* pbData,
  2732. IN OUT DWORD* pcbOptions
  2733. )
  2734. {
  2735. DWORD dwOptionType;
  2736. PPP_OPTION* pOption;
  2737. PPP_ASSERT(NULL != pBapCbLocal);
  2738. PPP_ASSERT(NULL != pbData);
  2739. PPP_ASSERT(NULL != pcbOptions);
  2740. pOption = (PPP_OPTION *) pbData;
  2741. for (dwOptionType = 1; dwOptionType <= BAP_OPTION_LIMIT;
  2742. dwOptionType++)
  2743. {
  2744. if (dwOptions & (1 << dwOptionType))
  2745. {
  2746. if (!FMakeBapOption(pBapCbLocal, dwOptionType, &pOption,
  2747. pcbOptions))
  2748. {
  2749. return(FALSE);
  2750. }
  2751. }
  2752. }
  2753. return(TRUE);
  2754. }
  2755. /*
  2756. Returns:
  2757. TRUE: Success
  2758. FALSE: Failure
  2759. Description:
  2760. Sends the BAP packet in pPcb->pSendBuf. dwId is the Identifier and dwLength
  2761. is the length of the BAP Datagram. We also add a timeout element so that we
  2762. can retransmit the datagram if it doesn't reach the peer. fInsertInTimerQ
  2763. is TRUE if an element has to be inserted in the timer queue.
  2764. */
  2765. BOOL
  2766. FSendBapPacket(
  2767. IN PCB* pPcb,
  2768. IN DWORD dwId,
  2769. IN DWORD dwLength,
  2770. IN BOOL fInsertInTimerQ
  2771. )
  2772. {
  2773. DWORD dwErr;
  2774. LCPCB* pLcpCb;
  2775. PPP_ASSERT(NULL != pPcb);
  2776. PPP_ASSERT(0xFF >= dwId);
  2777. pLcpCb = (LCPCB *)(LCPCB*)(pPcb->LcpCb.pWorkBuf);
  2778. PPP_ASSERT(NULL != pLcpCb);
  2779. if (dwLength > LCP_DEFAULT_MRU && dwLength > pLcpCb->Remote.Work.MRU)
  2780. {
  2781. BapTrace("FSendBapPacket: BAP packet too long. Length = %d. MRU = %d",
  2782. dwLength, pLcpCb->Remote.Work.MRU);
  2783. return(FALSE);
  2784. }
  2785. dwLength += PPP_PACKET_HDR_LEN;
  2786. PPP_ASSERT(dwLength <= 0xFFFF);
  2787. LogBapPacket(FALSE /* fReceived */, pPcb->hPort, pPcb->pBcb, pPcb->pSendBuf,
  2788. dwLength);
  2789. if ((dwErr = PortSendOrDisconnect(pPcb, dwLength)) != NO_ERROR)
  2790. {
  2791. BapTrace("FSendBapPacket: PortSendOrDisconnect failed and returned %d",
  2792. dwErr);
  2793. return(FALSE);
  2794. }
  2795. if (fInsertInTimerQ)
  2796. {
  2797. InsertInTimerQ(pPcb->pBcb->dwBundleId, pPcb->pBcb->hConnection, dwId,
  2798. PPP_BAP_PROTOCOL, FALSE /* fAuthenticator */, TIMER_EVENT_TIMEOUT,
  2799. pPcb->RestartTimer);
  2800. }
  2801. return(TRUE);
  2802. }
  2803. /*
  2804. Returns:
  2805. TRUE: Success
  2806. FALSE: Failure
  2807. Description:
  2808. Builds a BAP Request or Indication Datagram using the options specified by
  2809. pBcbLocal->BapCb.dwOptions and the values in pBcbLocal->BapCb and sends it.
  2810. */
  2811. BOOL
  2812. FSendBapRequest(
  2813. IN BCB* pBcbLocal
  2814. )
  2815. {
  2816. DWORD dwLength;
  2817. BAPCB* pBapCbLocal;
  2818. PPP_CONFIG* pSendConfig;
  2819. PCB* pPcb;
  2820. PPP_ASSERT(NULL != pBcbLocal);
  2821. pBapCbLocal = &(pBcbLocal->BapCb);
  2822. pPcb = GetPCBPointerFromBCB(pBcbLocal);
  2823. if (NULL == pPcb)
  2824. {
  2825. BapTrace("FSendBapRequest: No links in HCONN 0x%x!",
  2826. pBcbLocal->hConnection);
  2827. return(FALSE);
  2828. }
  2829. pSendConfig = (PPP_CONFIG *)(pPcb->pSendBuf->Information);
  2830. // Remaining free space in buffer, ie size of pSendConfig->Data
  2831. dwLength = LCP_DEFAULT_MRU - PPP_PACKET_HDR_LEN - PPP_CONFIG_HDR_LEN;
  2832. if (!FBuildBapOptionList(pBapCbLocal, pBapCbLocal->dwOptions,
  2833. pSendConfig->Data, &dwLength))
  2834. {
  2835. return(FALSE);
  2836. }
  2837. dwLength = LCP_DEFAULT_MRU - PPP_PACKET_HDR_LEN - dwLength;
  2838. HostToWireFormat16(PPP_BAP_PROTOCOL, pPcb->pSendBuf->Protocol);
  2839. PPP_ASSERT(pBapCbLocal->dwType <= 0xFF);
  2840. pSendConfig->Code = (BYTE)(pBapCbLocal->dwType);
  2841. PPP_ASSERT(pBapCbLocal->dwId <= 0xFF);
  2842. pSendConfig->Id = (BYTE)(pBapCbLocal->dwId);
  2843. PPP_ASSERT(dwLength <= 0xFFFF);
  2844. HostToWireFormat16((WORD)dwLength, pSendConfig->Length);
  2845. return(FSendBapPacket(pPcb, pBapCbLocal->dwId, dwLength,
  2846. TRUE /* fInsertInTimerQ */));
  2847. }
  2848. /*
  2849. Returns:
  2850. TRUE: Success
  2851. FALSE: Failure
  2852. Description:
  2853. Same as FSendBapRequest, except that pBcbLocal->BapCb.dwRetryCount is
  2854. initialized. FSendInitialBapRequest should be used to send the first BAP
  2855. Request or Indication Datagram and FSendBapRequest should be used to send
  2856. the subsequent datagrams after timeouts.
  2857. */
  2858. BOOL
  2859. FSendInitialBapRequest(
  2860. IN BCB* pBcbLocal
  2861. )
  2862. {
  2863. BAPCB* pBapCbLocal;
  2864. PPP_ASSERT(NULL != pBcbLocal);
  2865. pBapCbLocal = &(pBcbLocal->BapCb);
  2866. pBapCbLocal->dwRetryCount = PppConfigInfo.MaxConfigure;
  2867. if (BAP_PACKET_STATUS_IND == pBapCbLocal->dwType)
  2868. {
  2869. /*
  2870. Call-Status-Indication packets MUST use the same Identifier as was used
  2871. by the original Call-Request or Callback-Request that was used to
  2872. initiate the call.
  2873. */
  2874. pBapCbLocal->dwId = pBapCbLocal->dwStatusIndicationId;
  2875. }
  2876. else
  2877. {
  2878. IncrementId(pBcbLocal);
  2879. }
  2880. return(FSendBapRequest(pBcbLocal));
  2881. }
  2882. /*
  2883. Returns:
  2884. TRUE: Success
  2885. FALSE: Failure
  2886. Description:
  2887. Builds a BAP Response Datagram using the options specified by dwOptions and
  2888. the values in pBcbLocal->BapCb and sends it. The BAP Datagram Type,
  2889. Identifier, and Response Code are specified in dwType, dwId, and
  2890. dwResponseCode.
  2891. We cannot use dwOptions and dwType from pBcbLocal->BapCb because we
  2892. sometimes call FSendBapResponse without calling FFillBapCb first. We may be
  2893. in a BAP_STATE_SENT_* at this point, and we don't want to modify
  2894. pBcbLocal->BapCb.
  2895. */
  2896. BOOL
  2897. FSendBapResponse(
  2898. IN BCB* pBcbLocal,
  2899. IN DWORD dwOptions,
  2900. IN DWORD dwType,
  2901. IN DWORD dwId,
  2902. IN DWORD dwResponseCode
  2903. )
  2904. {
  2905. DWORD dwLength;
  2906. BAPCB* pBapCbLocal;
  2907. BAP_RESPONSE* pBapResponse;
  2908. PCB* pPcb;
  2909. PPP_ASSERT(NULL != pBcbLocal);
  2910. pBapCbLocal = &(pBcbLocal->BapCb);
  2911. pPcb = GetPCBPointerFromBCB(pBcbLocal);
  2912. if (NULL == pPcb)
  2913. {
  2914. BapTrace("FSendBapResponse: No links in HCONN 0x%x!",
  2915. pBcbLocal->hConnection);
  2916. return(FALSE);
  2917. }
  2918. pBapResponse = (BAP_RESPONSE *)(pPcb->pSendBuf->Information);
  2919. // Remaining free space in buffer, ie size of pBapResponse->Data
  2920. dwLength = LCP_DEFAULT_MRU - PPP_PACKET_HDR_LEN - BAP_RESPONSE_HDR_LEN;
  2921. if (!FBuildBapOptionList(pBapCbLocal, dwOptions, pBapResponse->Data,
  2922. &dwLength))
  2923. {
  2924. return(FALSE);
  2925. }
  2926. dwLength = LCP_DEFAULT_MRU - PPP_PACKET_HDR_LEN - dwLength;
  2927. HostToWireFormat16(PPP_BAP_PROTOCOL, pPcb->pSendBuf->Protocol);
  2928. PPP_ASSERT(dwType <= 0xFF);
  2929. pBapResponse->Type = (BYTE) dwType;
  2930. PPP_ASSERT(dwId <= 0xFF);
  2931. pBapResponse->Id = (BYTE) dwId;
  2932. PPP_ASSERT(dwLength <= 0xFFFF);
  2933. HostToWireFormat16((WORD)dwLength, pBapResponse->Length);
  2934. PPP_ASSERT(dwResponseCode <= 0xFF);
  2935. pBapResponse->ResponseCode = (BYTE) dwResponseCode;
  2936. return(FSendBapPacket(pPcb, dwId, dwLength, FALSE /* fInsertInTimerQ */));
  2937. }
  2938. /*
  2939. Returns:
  2940. void
  2941. Description:
  2942. Called when NDISWAN determines that a link has to be added to the bundle
  2943. represented pBcbLocal
  2944. */
  2945. VOID
  2946. BapEventAddLink(
  2947. IN BCB* pBcbLocal
  2948. )
  2949. {
  2950. BAP_STATE* pBapState;
  2951. PCB* pPcbLocal;
  2952. BAPCB* pBapCbLocal;
  2953. PPP_ASSERT(NULL != pBcbLocal);
  2954. pBapState = &(pBcbLocal->BapCb.BapState);
  2955. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  2956. if (!(pBcbLocal->fFlags & BCBFLAG_CAN_DO_BAP))
  2957. {
  2958. BapTrace("BapEventAddLink called on HCONN 0x%x without BACP",
  2959. pBcbLocal->hConnection);
  2960. return;
  2961. }
  2962. BapTrace(" ");
  2963. BapTrace("BapEventAddLink on HCONN 0x%x", pBcbLocal->hConnection);
  2964. if (pBcbLocal->fFlags & BCBFLAG_LISTENING)
  2965. {
  2966. BapTrace("Still listening; must ignore BapEventAddLink");
  2967. return;
  2968. }
  2969. switch(*pBapState)
  2970. {
  2971. case BAP_STATE_INITIAL:
  2972. if (pBcbLocal->fFlags & BCBFLAG_CAN_ACCEPT_CALLS)
  2973. {
  2974. // If we can accept calls, we prefer to be called (to save us the
  2975. // cost of calling).
  2976. if (FFillBapCb(BAP_PACKET_CALLBACK_REQ, pBcbLocal,
  2977. NULL /* pBapCbRemote */))
  2978. {
  2979. pPcbLocal = GetPCBPointerFromBCB(pBcbLocal);
  2980. pBapCbLocal = &(pBcbLocal->BapCb);
  2981. if (NULL == pPcbLocal)
  2982. {
  2983. BapTrace("BapEventRecvCallOrCallbackReq: No links in "
  2984. "HCONN 0x%x!",
  2985. pBcbLocal->hConnection);
  2986. return;
  2987. }
  2988. if ((pBcbLocal->fFlags & BCBFLAG_IS_SERVER) ||
  2989. (ROUTER_IF_TYPE_FULL_ROUTER ==
  2990. pPcbLocal->pBcb->InterfaceInfo.IfType) ||
  2991. FListenForCall(pBapCbLocal->szPortName,
  2992. pBapCbLocal->dwSubEntryIndex, pPcbLocal))
  2993. {
  2994. // Servers and routers are already listening. We have to
  2995. // call FListenForCall() only for non-router clients.
  2996. // We do a listen first and then send the Callback-Request
  2997. // because the peer may send an ACK and call back
  2998. // immediately before we have a chance to do a listen.
  2999. if (FSendInitialBapRequest(pBcbLocal))
  3000. {
  3001. *pBapState = BAP_STATE_SENT_CALLBACK_REQ;
  3002. BapTrace("BAP state change to %s on HCONN 0x%x",
  3003. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3004. return;
  3005. }
  3006. }
  3007. // FListenForCall may have failed because we chose an
  3008. // inappropriate port. Sending a Call-Request will not work
  3009. // because, most probably, we will select the same port.
  3010. return;
  3011. }
  3012. }
  3013. // We cannot accept calls, so we will call.
  3014. if ((pBcbLocal->fFlags & BCBFLAG_CAN_CALL) &&
  3015. FFillBapCb(BAP_PACKET_CALL_REQ, pBcbLocal,
  3016. NULL /* pBapCbRemote */))
  3017. {
  3018. if (FSendInitialBapRequest(pBcbLocal))
  3019. {
  3020. *pBapState = BAP_STATE_SENT_CALL_REQ;
  3021. BapTrace("BAP state change to %s on HCONN 0x%x",
  3022. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3023. }
  3024. }
  3025. break;
  3026. default:
  3027. BapTrace("BapEventAddLink ignored on HCONN 0x%x from state %s.",
  3028. pBcbLocal->hConnection, SzBapStateName[*pBapState]);
  3029. break;
  3030. }
  3031. }
  3032. /*
  3033. Returns:
  3034. void
  3035. Description:
  3036. Called when NDISWAN determines that a link has to be dropped from the
  3037. bundle represented by pBcbLocal
  3038. */
  3039. VOID
  3040. BapEventDropLink(
  3041. IN BCB* pBcbLocal
  3042. )
  3043. {
  3044. BAP_STATE* pBapState;
  3045. BAPCB* pBapCbLocal;
  3046. PPP_ASSERT(NULL != pBcbLocal);
  3047. pBapCbLocal = &(pBcbLocal->BapCb);
  3048. pBapState = &(pBapCbLocal->BapState);
  3049. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3050. if (!(pBcbLocal->fFlags & BCBFLAG_CAN_DO_BAP))
  3051. {
  3052. BapTrace("BapEventAddLink called on HCONN 0x%x without BACP",
  3053. pBcbLocal->hConnection);
  3054. return;
  3055. }
  3056. BapTrace(" ");
  3057. BapTrace("BapEventDropLink on HCONN 0x%x", pBcbLocal->hConnection);
  3058. switch(*pBapState)
  3059. {
  3060. case BAP_STATE_INITIAL:
  3061. if (FFillBapCb(BAP_PACKET_DROP_REQ, pBcbLocal,
  3062. NULL /* pBapCbRemote */))
  3063. {
  3064. // See note "Dropping Links" at the top of the file
  3065. pBapCbLocal->dwLinkCount = NumLinksInBundle(pBcbLocal);
  3066. pBapCbLocal->fForceDropOnNak = TRUE;
  3067. if (FSendInitialBapRequest(pBcbLocal))
  3068. {
  3069. *pBapState = BAP_STATE_SENT_DROP_REQ;
  3070. BapTrace("BAP state change to %s on HCONN 0x%x",
  3071. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3072. }
  3073. }
  3074. break;
  3075. case BAP_STATE_SENT_CALL_REQ:
  3076. case BAP_STATE_SENT_CALLBACK_REQ:
  3077. // We wanted to add a link, but we have now changed our minds.
  3078. *pBapState = BAP_STATE_INITIAL;
  3079. BapTrace("BAP state change to %s on HCONN 0x%x",
  3080. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3081. // Do not retransmit the request.
  3082. RemoveFromTimerQ(pBcbLocal->dwBundleId, pBapCbLocal->dwId,
  3083. PPP_BAP_PROTOCOL, FALSE /* fAuthenticator */, TIMER_EVENT_TIMEOUT);
  3084. break;
  3085. default:
  3086. BapTrace("BapEventDropLink ignored on HCONN 0x%x from state %s.",
  3087. pBcbLocal->hConnection, SzBapStateName[*pBapState]);
  3088. break;
  3089. }
  3090. }
  3091. /*
  3092. Returns:
  3093. void
  3094. Description:
  3095. Called when a Call-Request or Callback-Request BAP Datagram is received.
  3096. fCall is TRUE if it is a Call-Request. pBcbLocal represents the bundle that
  3097. receives the Request. The BAP Datagram Options sent by the peer are in
  3098. *pBapCbRemote. The Identifier of the BAP Datagram sent by the peer is in
  3099. dwId.
  3100. */
  3101. VOID
  3102. BapEventRecvCallOrCallbackReq(
  3103. IN BOOL fCall,
  3104. IN BCB* pBcbLocal,
  3105. IN BAPCB* pBapCbRemote,
  3106. IN DWORD dwId
  3107. )
  3108. {
  3109. BAPCB* pBapCbLocal;
  3110. DWORD dwOptions = 0;
  3111. DWORD dwResponseCode;
  3112. DWORD dwPacketType = fCall ? BAP_PACKET_CALL_RESP :
  3113. BAP_PACKET_CALLBACK_RESP;
  3114. BAP_STATE* pBapState;
  3115. CHAR* szRequest = fCall ? "Call-Request" : "Callback-Request";
  3116. PCB* pPcbLocal;
  3117. BOOL fServer;
  3118. BAP_CALL_RESULT BapCallResult;
  3119. PPP_ASSERT(NULL != pBcbLocal);
  3120. PPP_ASSERT(NULL != pBapCbRemote);
  3121. PPP_ASSERT(0xFF >= dwId);
  3122. pBapCbLocal = &(pBcbLocal->BapCb);
  3123. pBapState = &(pBapCbLocal->BapState);
  3124. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3125. BapTrace("BapEventRecvCallOrCallbackReq on HCONN 0x%x",
  3126. pBcbLocal->hConnection);
  3127. if ((!fCall && !(pBcbLocal->fFlags & BCBFLAG_CAN_CALL)) ||
  3128. (fCall && !(pBcbLocal->fFlags & BCBFLAG_CAN_ACCEPT_CALLS)))
  3129. {
  3130. BapTrace("Rejecting %s on HCONN 0x%x", szRequest,
  3131. pBcbLocal->hConnection);
  3132. dwResponseCode = BAP_RESPONSE_REJ;
  3133. }
  3134. else if (FUpperLimitReached(pBcbLocal))
  3135. {
  3136. BapTrace("Full-Nak'ing %s on HCONN 0x%x: upper limit reached",
  3137. szRequest, pBcbLocal->hConnection);
  3138. dwResponseCode = BAP_RESPONSE_FULL_NAK;
  3139. }
  3140. else
  3141. {
  3142. switch (*pBapState)
  3143. {
  3144. case BAP_STATE_SENT_DROP_REQ:
  3145. case BAP_STATE_SENT_STATUS_IND:
  3146. case BAP_STATE_CALLING:
  3147. case BAP_STATE_LISTENING:
  3148. BapTrace("Nak'ing %s on HCONN 0x%x from state %s",
  3149. szRequest, pBcbLocal->hConnection, SzBapStateName[*pBapState]);
  3150. dwResponseCode = BAP_RESPONSE_NAK;
  3151. break;
  3152. case BAP_STATE_INITIAL:
  3153. case BAP_STATE_SENT_CALL_REQ:
  3154. case BAP_STATE_SENT_CALLBACK_REQ:
  3155. if ((*pBapState != BAP_STATE_INITIAL && FFavoredPeer(pBcbLocal)) ||
  3156. (*pBapState == BAP_STATE_INITIAL && !FOkToAddLink(pBcbLocal)))
  3157. {
  3158. // If a race condition occurs and we are the favored peer, then
  3159. // NAK. If our algo does not allow us to add a link (based on
  3160. // the bandwidth utilization), then NAK.
  3161. BapTrace("Nak'ing %s on HCONN 0x%x from state %s%s",
  3162. szRequest,
  3163. pBcbLocal->hConnection,
  3164. SzBapStateName[*pBapState],
  3165. *pBapState != BAP_STATE_INITIAL ?
  3166. ": we are the favored peer" : "");
  3167. dwResponseCode = BAP_RESPONSE_NAK;
  3168. }
  3169. else
  3170. {
  3171. // State is Initial and it is OK to add a link or
  3172. // State is Sent-Call[back]_Req and we are not the favored peer
  3173. // (so we should drop our request and agree to the peer's
  3174. // request).
  3175. if (*pBapState != BAP_STATE_INITIAL)
  3176. {
  3177. *pBapState = BAP_STATE_INITIAL;
  3178. BapTrace("BAP state change to %s on HCONN 0x%x: we are not "
  3179. "the favored peer",
  3180. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3181. // Do not retransmit the request.
  3182. RemoveFromTimerQ(pBcbLocal->dwBundleId, pBapCbLocal->dwId,
  3183. PPP_BAP_PROTOCOL, FALSE /* fAuthenticator */,
  3184. TIMER_EVENT_TIMEOUT);
  3185. }
  3186. if (FFillBapCb(dwPacketType, pBcbLocal, pBapCbRemote))
  3187. {
  3188. BapTrace("Ack'ing %s on HCONN 0x%x",
  3189. szRequest, pBcbLocal->hConnection);
  3190. dwOptions = pBapCbLocal->dwOptions;
  3191. dwResponseCode = BAP_RESPONSE_ACK;
  3192. }
  3193. else if (pBapCbLocal->dwOptions & BAP_N_LINK_TYPE)
  3194. {
  3195. // We don't have the link type requested
  3196. BapTrace("Nak'ing %s on HCONN 0x%x: link type not available",
  3197. szRequest, pBcbLocal->hConnection);
  3198. dwOptions = pBapCbLocal->dwOptions;
  3199. dwResponseCode = BAP_RESPONSE_NAK;
  3200. }
  3201. else
  3202. {
  3203. // We don't know our own phone number or no link is
  3204. // available
  3205. BapTrace("Full-Nak'ing %s on HCONN 0x%x: no link available",
  3206. szRequest, pBcbLocal->hConnection);
  3207. dwResponseCode = BAP_RESPONSE_FULL_NAK;
  3208. }
  3209. }
  3210. break;
  3211. default:
  3212. PPP_ASSERT(FALSE);
  3213. BapTrace("In weird state: %d", *pBapState);
  3214. return;
  3215. }
  3216. }
  3217. pPcbLocal = GetPCBPointerFromBCB(pBcbLocal);
  3218. if (NULL == pPcbLocal)
  3219. {
  3220. BapTrace("BapEventRecvCallOrCallbackReq: No links in HCONN 0x%x!",
  3221. pBcbLocal->hConnection);
  3222. return;
  3223. }
  3224. fServer = (pBcbLocal->fFlags & BCBFLAG_IS_SERVER) != 0;
  3225. if (BAP_RESPONSE_ACK == dwResponseCode &&
  3226. fCall && !fServer &&
  3227. (ROUTER_IF_TYPE_FULL_ROUTER != pBcbLocal->InterfaceInfo.IfType))
  3228. {
  3229. // If we received a Call-Request and agreed to accept the call, we
  3230. // have to start listening if we are a non-router client. Servers
  3231. // and routers are always listening, so we do nothing.
  3232. // We do a listen first and then send the ACK to the Call-Request
  3233. // because the peer may start dialing as soon as it gets the ACK.
  3234. if (FListenForCall(pBapCbLocal->szPortName,
  3235. pBapCbLocal->dwSubEntryIndex, pPcbLocal))
  3236. {
  3237. *pBapState = BAP_STATE_LISTENING;
  3238. BapTrace("BAP state change to %s on HCONN 0x%x",
  3239. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3240. }
  3241. else
  3242. {
  3243. BapTrace("Nak'ing %s on HCONN 0x%x",
  3244. szRequest, pBcbLocal->hConnection);
  3245. dwOptions = 0;
  3246. dwResponseCode = BAP_RESPONSE_NAK;
  3247. }
  3248. }
  3249. if (FSendBapResponse(pBcbLocal, dwOptions, dwPacketType, dwId,
  3250. dwResponseCode))
  3251. {
  3252. if (!fCall && (BAP_RESPONSE_ACK == dwResponseCode))
  3253. {
  3254. // We received a Callback-Request and we agreed to call.
  3255. if (FCallInitial(pBcbLocal, pBapCbRemote))
  3256. {
  3257. pBapCbLocal->dwStatusIndicationId = dwId;
  3258. *pBapState = BAP_STATE_CALLING;
  3259. BapTrace("BAP state change to %s on HCONN 0x%x",
  3260. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3261. }
  3262. else
  3263. {
  3264. BapCallResult.dwResult = ERROR_INVALID_FUNCTION;
  3265. BapCallResult.hRasConn = (HRASCONN)-1;
  3266. BapEventCallResult(pBcbLocal, &BapCallResult);
  3267. }
  3268. }
  3269. }
  3270. }
  3271. /*
  3272. Returns:
  3273. void
  3274. Description:
  3275. Called when a Link-Drop-Query-Request BAP Datagram is received. pBcbLocal
  3276. represents the bundle that receives the Request. The BAP Datagram Options
  3277. sent by the peer are in *pBapCbRemote. The Identifier of the BAP Datagram
  3278. sent by the peer is in dwId.
  3279. */
  3280. VOID
  3281. BapEventRecvDropReq(
  3282. IN BCB* pBcbLocal,
  3283. IN BAPCB* pBapCbRemote,
  3284. IN DWORD dwId
  3285. )
  3286. {
  3287. BAPCB* pBapCbLocal;
  3288. BAP_STATE* pBapState;
  3289. DWORD dwResponseCode;
  3290. PCB* pPcbDrop;
  3291. CHAR* psz[2];
  3292. PPP_ASSERT(NULL != pBcbLocal);
  3293. PPP_ASSERT(NULL != pBapCbRemote);
  3294. PPP_ASSERT(0xFF >= dwId);
  3295. pBapCbLocal = &(pBcbLocal->BapCb);
  3296. pBapState = &(pBapCbLocal->BapState);
  3297. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3298. BapTrace("BapEventRecvDropReq on HCONN 0x%x", pBcbLocal->hConnection);
  3299. if (!(pBcbLocal->fFlags & BCBFLAG_IS_SERVER))
  3300. {
  3301. psz[0] = pBcbLocal->szEntryName;
  3302. psz[1] = pBcbLocal->szLocalUserName;
  3303. PppLogInformation(ROUTERLOG_BAP_WILL_DISCONNECT, 2, psz);
  3304. }
  3305. if (NumLinksInBundle(pBcbLocal) == 1)
  3306. {
  3307. // Do not agree to drop the last link
  3308. BapTrace("Full-Nak'ing Link-Drop-Query-Request on HCONN 0x%x: last link",
  3309. pBcbLocal->hConnection);
  3310. dwResponseCode = BAP_RESPONSE_FULL_NAK;
  3311. }
  3312. else
  3313. {
  3314. switch(*pBapState)
  3315. {
  3316. case BAP_STATE_SENT_CALL_REQ:
  3317. case BAP_STATE_SENT_CALLBACK_REQ:
  3318. case BAP_STATE_SENT_STATUS_IND:
  3319. case BAP_STATE_CALLING:
  3320. case BAP_STATE_LISTENING:
  3321. BapTrace("Nak'ing Link-Drop-Query-Request on HCONN 0x%x from "
  3322. "state %s",
  3323. pBcbLocal->hConnection, SzBapStateName[*pBapState]);
  3324. dwResponseCode = BAP_RESPONSE_NAK;
  3325. break;
  3326. case BAP_STATE_INITIAL:
  3327. case BAP_STATE_SENT_DROP_REQ:
  3328. if (!FGetPcbOfLink(pBcbLocal, pBapCbRemote->dwLinkDiscriminator,
  3329. FALSE /* fRemote */, &pPcbDrop) ||
  3330. (*pBapState != BAP_STATE_INITIAL && FFavoredPeer(pBcbLocal)) ||
  3331. (*pBapState == BAP_STATE_INITIAL &&
  3332. !FOkToDropLink(pBcbLocal, pBapCbRemote)))
  3333. {
  3334. // The link discriminator sent by the peer is wrong. Or
  3335. // There is a race condition and we are the favored peer. Or
  3336. // Our algo does not allow us to drop a link (based on the
  3337. // bandwidth utilization).
  3338. BapTrace("Nak'ing Link-Drop-Query-Request on HCONN 0x%x from "
  3339. "state %s%s",
  3340. pBcbLocal->hConnection,
  3341. SzBapStateName[*pBapState],
  3342. *pBapState != BAP_STATE_INITIAL ?
  3343. ": we are the favored peer" : "");
  3344. dwResponseCode = BAP_RESPONSE_NAK;
  3345. }
  3346. else
  3347. {
  3348. // State is Initial and it is OK to drop a link or
  3349. // State is Sent-Drop_Req and we are not the favored peer
  3350. // (so we should drop our request and agree to the peer's
  3351. // request).
  3352. if (*pBapState != BAP_STATE_INITIAL)
  3353. {
  3354. *pBapState = BAP_STATE_INITIAL;
  3355. BapTrace("BAP state change to %s on HCONN 0x%x: we are not "
  3356. "the favored peer",
  3357. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3358. // We will get a NAK from the peer. That is OK. He will be
  3359. // dropping a link. We don't have to drop any link.
  3360. pBapCbLocal->fForceDropOnNak = FALSE;
  3361. // Do not retransmit the request.
  3362. RemoveFromTimerQ(pBcbLocal->dwBundleId, pBapCbLocal->dwId,
  3363. PPP_BAP_PROTOCOL, FALSE /* fAuthenticator */,
  3364. TIMER_EVENT_TIMEOUT);
  3365. // Make sure that the peer will indeed drop this link.
  3366. InsertInTimerQ(pPcbDrop->dwPortId, pPcbDrop->hPort,
  3367. 0 /* Id */, 0 /* Protocol */,
  3368. FALSE /* fAuthenticator */,
  3369. TIMER_EVENT_FAV_PEER_TIMEOUT,
  3370. BAP_TIMEOUT_FAV_PEER);
  3371. }
  3372. BapTrace("Ack'ing Link-Drop-Query-Request on HCONN 0x%x",
  3373. pBcbLocal->hConnection);
  3374. dwResponseCode = BAP_RESPONSE_ACK;
  3375. }
  3376. break;
  3377. default:
  3378. PPP_ASSERT(FALSE);
  3379. }
  3380. }
  3381. FSendBapResponse(pBcbLocal, 0 /* dwOptions */, BAP_PACKET_DROP_RESP,
  3382. dwId, dwResponseCode);
  3383. }
  3384. /*
  3385. Returns:
  3386. void
  3387. Description:
  3388. Called when a Call-Status-Indication BAP Datagram is received. pBcbLocal
  3389. represents the bundle that receives the Indication. The BAP Datagram
  3390. Options sent by the peer are in *pBapCbRemote. The Identifier of the BAP
  3391. Datagram sent by the peer is in dwId.
  3392. */
  3393. VOID
  3394. BapEventRecvStatusInd(
  3395. IN BCB* pBcbLocal,
  3396. IN BAPCB* pBapCbRemote,
  3397. IN DWORD dwId
  3398. )
  3399. {
  3400. PPP_ASSERT(NULL != pBcbLocal);
  3401. PPP_ASSERT(NULL != pBapCbRemote);
  3402. PPP_ASSERT(0xFF >= dwId);
  3403. BapTrace("BapEventRecvStatusInd on HCONN 0x%x", pBcbLocal->hConnection);
  3404. FSendBapResponse(pBcbLocal, 0 /* dwOptions */, BAP_PACKET_STAT_RESP,
  3405. dwId, BAP_RESPONSE_ACK);
  3406. }
  3407. /*
  3408. Returns:
  3409. void
  3410. Description:
  3411. Called when a Call-Response or Callback-Response BAP Datagram is received.
  3412. fCall is TRUE iff it is a Call-Response. pBcbLocal represents the bundle
  3413. that receives the Request. The BAP Datagram Options sent by the peer are in
  3414. *pBapCbRemote. The Identifier and Response Code of the BAP Datagram sent by
  3415. the peer are in dwId and dwResponseCode.
  3416. */
  3417. VOID
  3418. BapEventRecvCallOrCallbackResp(
  3419. IN BOOL fCall,
  3420. IN BCB* pBcbLocal,
  3421. IN BAPCB* pBapCbRemote,
  3422. IN DWORD dwId,
  3423. IN DWORD dwResponseCode
  3424. )
  3425. {
  3426. BAPCB* pBapCbLocal;
  3427. BAP_STATE* pBapState;
  3428. BAP_CALL_RESULT BapCallResult;
  3429. PPP_ASSERT(NULL != pBcbLocal);
  3430. PPP_ASSERT(NULL != pBapCbRemote);
  3431. PPP_ASSERT(0xFF >= dwId);
  3432. pBapCbLocal = &(pBcbLocal->BapCb);
  3433. pBapState = &(pBapCbLocal->BapState);
  3434. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3435. BapTrace("BapEventRecvCallOrCallbackResp on HCONN 0x%x",
  3436. pBcbLocal->hConnection);
  3437. if ((fCall && (*pBapState != BAP_STATE_SENT_CALL_REQ)) ||
  3438. (!fCall && (*pBapState != BAP_STATE_SENT_CALLBACK_REQ)) ||
  3439. dwId != pBapCbLocal->dwId)
  3440. {
  3441. BapTrace("Discarding unexpected Call[back]-Response (ID = %d) on "
  3442. "HCONN 0x%x",
  3443. dwId, pBcbLocal->hConnection);
  3444. return;
  3445. }
  3446. *pBapState = BAP_STATE_INITIAL;
  3447. BapTrace("BAP state change to %s on HCONN 0x%x",
  3448. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3449. // Do not retransmit the request.
  3450. RemoveFromTimerQ(pBcbLocal->dwBundleId, dwId, PPP_BAP_PROTOCOL,
  3451. FALSE /* fAuthenticator */, TIMER_EVENT_TIMEOUT);
  3452. switch(dwResponseCode)
  3453. {
  3454. case BAP_RESPONSE_ACK:
  3455. if (fCall)
  3456. {
  3457. if (FCallInitial(pBcbLocal, pBapCbRemote))
  3458. {
  3459. pBapCbLocal->dwStatusIndicationId = dwId;
  3460. *pBapState = BAP_STATE_CALLING;
  3461. BapTrace("BAP state change to %s on HCONN 0x%x",
  3462. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3463. }
  3464. else
  3465. {
  3466. BapCallResult.dwResult = ERROR_INVALID_FUNCTION;
  3467. BapCallResult.hRasConn = (HRASCONN)-1;
  3468. BapEventCallResult(pBcbLocal, &BapCallResult);
  3469. }
  3470. }
  3471. break;
  3472. case BAP_RESPONSE_NAK:
  3473. if (pBapCbRemote->dwOptions & BAP_N_LINK_TYPE)
  3474. {
  3475. // The peer wants to use a different link type
  3476. if (FFillBapCb(
  3477. fCall ? BAP_PACKET_CALL_REQ : BAP_PACKET_CALLBACK_REQ,
  3478. pBcbLocal, pBapCbRemote))
  3479. {
  3480. if (FSendInitialBapRequest(pBcbLocal))
  3481. {
  3482. *pBapState = fCall ?
  3483. BAP_STATE_SENT_CALL_REQ : BAP_STATE_SENT_CALLBACK_REQ;
  3484. BapTrace("BAP state change to %s on HCONN 0x%x",
  3485. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3486. }
  3487. }
  3488. else
  3489. {
  3490. BapTrace("We don't have the reqd link type: %d on HCONN 0x%x",
  3491. pBapCbRemote->dwLinkType, pBcbLocal->hConnection);
  3492. }
  3493. }
  3494. else
  3495. {
  3496. // The original Request MAY be retried after a little while.
  3497. // So we will not do anything here.
  3498. }
  3499. break;
  3500. case BAP_RESPONSE_REJ:
  3501. // We always try to send a Callback-Request first. If the peer rejects
  3502. // it, we can try to send a Call-Request. If the peer rejects a
  3503. // Call-Request, there is nothing that we can do.
  3504. pBcbLocal->fFlags |= (fCall ? BCBFLAG_PEER_CANT_ACCEPT_CALLS :
  3505. BCBFLAG_PEER_CANT_CALL);
  3506. if (pBcbLocal->fFlags & BCBFLAG_LISTENING)
  3507. {
  3508. BapTrace("Still listening; will not send Call-Request");
  3509. break;
  3510. }
  3511. if (!fCall && (pBcbLocal->fFlags & BCBFLAG_CAN_CALL))
  3512. {
  3513. if (FFillBapCb(BAP_PACKET_CALL_REQ, pBcbLocal,
  3514. NULL /* pBapCbRemote */))
  3515. {
  3516. if (FSendInitialBapRequest(pBcbLocal))
  3517. {
  3518. *pBapState = BAP_STATE_SENT_CALL_REQ;
  3519. BapTrace("BAP state change to %s on HCONN 0x%x",
  3520. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3521. }
  3522. }
  3523. }
  3524. break;
  3525. case BAP_RESPONSE_FULL_NAK:
  3526. // Do not try to add links till the total bandwidth of the bundle
  3527. // has changed. However, we don't know the total bw. So we will not
  3528. // do anything here. After all, this is not a MUST.
  3529. break;
  3530. default:
  3531. BapTrace("Unknown Response Code %d received on HCONN 0x%x",
  3532. dwResponseCode, pBcbLocal->hConnection);
  3533. break;
  3534. }
  3535. }
  3536. /*
  3537. Returns:
  3538. void
  3539. Description:
  3540. Called when a Link-Drop-Query-Response BAP Datagram is received. pBcbLocal
  3541. represents the bundle that receives the Response. The Identifier and
  3542. Response Code of the BAP Datagram sent by the peer are in dwId and
  3543. dwResponseCode.
  3544. */
  3545. VOID
  3546. BapEventRecvDropResp(
  3547. IN BCB* pBcbLocal,
  3548. IN DWORD dwId,
  3549. IN DWORD dwResponseCode
  3550. )
  3551. {
  3552. BAPCB* pBapCbLocal;
  3553. BAP_STATE* pBapState;
  3554. PCB* pPcbDrop;
  3555. PPP_ASSERT(NULL != pBcbLocal);
  3556. PPP_ASSERT(0xFF >= dwId);
  3557. pBapCbLocal = &(pBcbLocal->BapCb);
  3558. pBapState = &(pBapCbLocal->BapState);
  3559. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3560. BapTrace("BapEventRecvDropResp on HCONN 0x%x", pBcbLocal->hConnection);
  3561. if ((*pBapState != BAP_STATE_SENT_DROP_REQ) ||
  3562. dwId != pBapCbLocal->dwId)
  3563. {
  3564. BapTrace("Discarding unexpected Link-Drop-Query-Response (ID = %d) on "
  3565. "HCONN 0x%x",
  3566. dwId, pBcbLocal->hConnection);
  3567. return;
  3568. }
  3569. *pBapState = BAP_STATE_INITIAL;
  3570. BapTrace("BAP state change to %s on HCONN 0x%x",
  3571. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3572. // Do not retransmit the request.
  3573. RemoveFromTimerQ(pBcbLocal->dwBundleId, dwId, PPP_BAP_PROTOCOL,
  3574. FALSE /* fAuthenticator */, TIMER_EVENT_TIMEOUT);
  3575. switch(dwResponseCode)
  3576. {
  3577. default:
  3578. BapTrace("Unknown Response Code %d received on HCONN 0x%x",
  3579. dwResponseCode, pBcbLocal->hConnection);
  3580. // Fall through (perhaps we need to drop a link)
  3581. case BAP_RESPONSE_NAK:
  3582. case BAP_RESPONSE_REJ:
  3583. case BAP_RESPONSE_FULL_NAK:
  3584. if ( (NumLinksInBundle(pBcbLocal) < pBapCbLocal->dwLinkCount)
  3585. || !pBapCbLocal->fForceDropOnNak)
  3586. {
  3587. // Do not forcibly drop a link.
  3588. break;
  3589. }
  3590. // Fall through (to forcibly drop a link)
  3591. case BAP_RESPONSE_ACK:
  3592. if (FGetPcbOfLink(pBcbLocal, pBapCbLocal->dwLinkDiscriminator,
  3593. TRUE /* fRemote */, &pPcbDrop))
  3594. {
  3595. CHAR* psz[3];
  3596. if (!(pBcbLocal->fFlags & BCBFLAG_IS_SERVER))
  3597. {
  3598. psz[0] = pPcbDrop->pBcb->szEntryName;
  3599. psz[1] = pPcbDrop->pBcb->szLocalUserName;
  3600. psz[2] = pPcbDrop->szPortName;
  3601. PppLogInformation(ROUTERLOG_BAP_DISCONNECTED, 3, psz);
  3602. }
  3603. BapTrace("Dropping link with hPort %d from HCONN 0x%x",
  3604. pPcbDrop->hPort, pBcbLocal->hConnection);
  3605. pPcbDrop->LcpCb.dwError = ERROR_BAP_DISCONNECTED;
  3606. FsmClose(pPcbDrop, LCP_INDEX);
  3607. }
  3608. break;
  3609. }
  3610. }
  3611. /*
  3612. Returns:
  3613. void
  3614. Description:
  3615. Called when a Call-Status-Response BAP Datagram is received. pBcbLocal
  3616. represents the bundle that receives the Response. The Identifier and
  3617. Response Code of the BAP Datagram sent by the peer are in dwId and
  3618. dwResponseCode.
  3619. */
  3620. VOID
  3621. BapEventRecvStatusResp(
  3622. IN BCB* pBcbLocal,
  3623. IN DWORD dwId,
  3624. IN DWORD dwResponseCode
  3625. )
  3626. {
  3627. BAPCB* pBapCbLocal;
  3628. BAP_STATE* pBapState;
  3629. PPP_ASSERT(NULL != pBcbLocal);
  3630. PPP_ASSERT(0xFF >= dwId);
  3631. pBapCbLocal = &(pBcbLocal->BapCb);
  3632. pBapState = &(pBapCbLocal->BapState);
  3633. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3634. BapTrace("BapEventRecvStatusResp on HCONN 0x%x", pBcbLocal->hConnection);
  3635. if ((*pBapState != BAP_STATE_SENT_STATUS_IND) ||
  3636. dwId != pBapCbLocal->dwId)
  3637. {
  3638. BapTrace("Discarding unexpected Call-Status-Response (ID = %d) on "
  3639. "HCONN 0x%x",
  3640. dwId, pBcbLocal->hConnection);
  3641. return;
  3642. }
  3643. // Do not retransmit the indication.
  3644. RemoveFromTimerQ(pBcbLocal->dwBundleId, dwId, PPP_BAP_PROTOCOL,
  3645. FALSE /* fAuthenticator */, TIMER_EVENT_TIMEOUT);
  3646. if (pBapCbLocal->dwAction && FCall(pBcbLocal))
  3647. {
  3648. *pBapState = BAP_STATE_CALLING;
  3649. // BapEventRecvStatusResp or BapEventTimeout will get called at some
  3650. // point, and we will free pBapCbLocal->pbPhoneDeltaRemote.
  3651. }
  3652. else
  3653. {
  3654. *pBapState = BAP_STATE_INITIAL;
  3655. if (NULL != pBapCbLocal->pbPhoneDeltaRemote)
  3656. {
  3657. LOCAL_FREE(pBapCbLocal->pbPhoneDeltaRemote);
  3658. }
  3659. pBapCbLocal->pbPhoneDeltaRemote = NULL;
  3660. }
  3661. BapTrace("BAP state change to %s on HCONN 0x%x",
  3662. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3663. }
  3664. /*
  3665. Returns:
  3666. void
  3667. Description:
  3668. Called when a BAP Datagram is received. pBcbLocal represents the bundle
  3669. that receives the Datagram. pPacket is the PPP packet which contains the
  3670. Datagram. dwPacketLength is the number of bytes in the PPP packet.
  3671. */
  3672. VOID
  3673. BapEventReceive(
  3674. IN BCB* pBcbLocal,
  3675. IN PPP_PACKET* pPacket,
  3676. IN DWORD dwPacketLength
  3677. )
  3678. {
  3679. PPP_CONFIG* pConfig;
  3680. BAP_RESPONSE* pResponse;
  3681. DWORD dwLength;
  3682. DWORD dwType;
  3683. DWORD dwId;
  3684. BAPCB BapCbRemote;
  3685. PPP_ASSERT(NULL != pBcbLocal);
  3686. PPP_ASSERT(NULL != pPacket);
  3687. // We don't know whether we have received a request or a response. Let us
  3688. // grab pointers to both the request part and the response part.
  3689. pConfig = (PPP_CONFIG *)(pPacket->Information);
  3690. pResponse = (BAP_RESPONSE *)(pPacket->Information);
  3691. // The Length, Type, and Id are always found in the same place, both for
  3692. // requests and responses. So let us get those values, assuming that we have
  3693. // received a request.
  3694. dwLength = WireToHostFormat16(pConfig->Length);
  3695. dwType = pConfig->Code;
  3696. dwId = pConfig->Id;
  3697. LogBapPacket(TRUE /* fReceived */, (HPORT)-1 /* hPort */,
  3698. pBcbLocal, pPacket, dwPacketLength);
  3699. if ((dwLength > dwPacketLength - PPP_PACKET_HDR_LEN) ||
  3700. (dwLength < PPP_CONFIG_HDR_LEN) ||
  3701. (dwType > BAP_PACKET_LIMIT) ||
  3702. !FReadOptions(pPacket, dwType, dwLength, &BapCbRemote))
  3703. {
  3704. BapTrace("Silently discarding badly formed BAP packet");
  3705. return;
  3706. }
  3707. switch(dwType)
  3708. {
  3709. case BAP_PACKET_CALL_REQ:
  3710. BapEventRecvCallOrCallbackReq(
  3711. TRUE /* fCall */,
  3712. pBcbLocal,
  3713. &BapCbRemote,
  3714. dwId);
  3715. return;
  3716. case BAP_PACKET_CALL_RESP:
  3717. BapEventRecvCallOrCallbackResp(
  3718. TRUE /* fCall */,
  3719. pBcbLocal,
  3720. &BapCbRemote,
  3721. dwId,
  3722. pResponse->ResponseCode);
  3723. return;
  3724. case BAP_PACKET_CALLBACK_REQ:
  3725. BapEventRecvCallOrCallbackReq(
  3726. FALSE /* fCall */,
  3727. pBcbLocal,
  3728. &BapCbRemote,
  3729. dwId);
  3730. return;
  3731. case BAP_PACKET_CALLBACK_RESP:
  3732. BapEventRecvCallOrCallbackResp(
  3733. FALSE /* fCall */,
  3734. pBcbLocal,
  3735. &BapCbRemote,
  3736. dwId,
  3737. pResponse->ResponseCode);
  3738. return;
  3739. case BAP_PACKET_DROP_REQ:
  3740. BapEventRecvDropReq(
  3741. pBcbLocal,
  3742. &BapCbRemote,
  3743. dwId);
  3744. return;
  3745. case BAP_PACKET_DROP_RESP:
  3746. BapEventRecvDropResp(
  3747. pBcbLocal,
  3748. dwId,
  3749. pResponse->ResponseCode);
  3750. return;
  3751. case BAP_PACKET_STATUS_IND:
  3752. BapEventRecvStatusInd(
  3753. pBcbLocal,
  3754. &BapCbRemote,
  3755. dwId);
  3756. return;
  3757. case BAP_PACKET_STAT_RESP:
  3758. BapEventRecvStatusResp(
  3759. pBcbLocal,
  3760. dwId,
  3761. pResponse->ResponseCode);
  3762. return;
  3763. default:
  3764. // The check above should have caught this case.
  3765. PPP_ASSERT(FALSE);
  3766. return;
  3767. }
  3768. }
  3769. /*
  3770. Returns:
  3771. void
  3772. Description:
  3773. Called when a BAP Request or Indication packet times out while waiting for
  3774. a Response. pBcbLocal represents the bundle that the packet was sent on.
  3775. The Identifier of the BAP Datagram is in dwId.
  3776. */
  3777. VOID
  3778. BapEventTimeout(
  3779. IN BCB* pBcbLocal,
  3780. IN DWORD dwId
  3781. )
  3782. {
  3783. BAPCB* pBapCbLocal;
  3784. BAP_STATE* pBapState;
  3785. PCB* pPcbDrop;
  3786. PPP_ASSERT(NULL != pBcbLocal);
  3787. pBapCbLocal = &(pBcbLocal->BapCb);
  3788. pBapState = &(pBapCbLocal->BapState);
  3789. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3790. if (dwId != pBapCbLocal->dwId ||
  3791. *pBapState == BAP_STATE_INITIAL ||
  3792. *pBapState == BAP_STATE_CALLING)
  3793. {
  3794. BapTrace("Illegal timeout occurred. Id: %d, BapCb's Id: %d, "
  3795. "BAP state: %s",
  3796. dwId, pBapCbLocal->dwId, SzBapStateName[*pBapState]);
  3797. return;
  3798. }
  3799. BapTrace("BAP packet (Type: %s, ID: %d) sent on HCONN 0x%x timed out.",
  3800. pBapCbLocal->dwType <= BAP_PACKET_LIMIT ?
  3801. SzBapPacketName[pBapCbLocal->dwType] : "UNKNOWN",
  3802. dwId, pBcbLocal->hConnection);
  3803. if (pBapCbLocal->dwRetryCount > 0)
  3804. {
  3805. // Send the packet once again
  3806. (pBapCbLocal->dwRetryCount)--;
  3807. FSendBapRequest(pBcbLocal);
  3808. // BapEventRecvStatusResp or BapEventTimeout will get called at some
  3809. // point, and we will free pBapCbLocal->pbPhoneDeltaRemote.
  3810. }
  3811. else
  3812. {
  3813. // We have sent the packet too many times. Discard it now.
  3814. BapTrace("Request retry exceeded.");
  3815. if (*pBapState == BAP_STATE_SENT_DROP_REQ)
  3816. {
  3817. // The peer did not respond to our Link-Drop-Query-Request. Perhaps
  3818. // we need to forcibly drop the link.
  3819. if (NumLinksInBundle(pBcbLocal) >= pBapCbLocal->dwLinkCount &&
  3820. pBapCbLocal->fForceDropOnNak)
  3821. {
  3822. if (FGetPcbOfLink(pBcbLocal, pBapCbLocal->dwLinkDiscriminator,
  3823. TRUE /*fRemote */, &pPcbDrop))
  3824. {
  3825. CHAR* psz[3];
  3826. if (!(pBcbLocal->fFlags & BCBFLAG_IS_SERVER))
  3827. {
  3828. psz[0] = pPcbDrop->pBcb->szEntryName;
  3829. psz[1] = pPcbDrop->pBcb->szLocalUserName;
  3830. psz[2] = pPcbDrop->szPortName;
  3831. PppLogInformation(ROUTERLOG_BAP_DISCONNECTED, 3, psz);
  3832. }
  3833. BapTrace("Dropping link with hPort %d from HCONN 0x%x",
  3834. pPcbDrop->hPort, pBcbLocal->hConnection);
  3835. pPcbDrop->LcpCb.dwError = ERROR_BAP_DISCONNECTED;
  3836. FsmClose(pPcbDrop, LCP_INDEX);
  3837. }
  3838. }
  3839. }
  3840. if (NULL != pBapCbLocal->pbPhoneDeltaRemote)
  3841. {
  3842. LOCAL_FREE(pBapCbLocal->pbPhoneDeltaRemote);
  3843. }
  3844. pBapCbLocal->pbPhoneDeltaRemote = NULL;
  3845. *pBapState = BAP_STATE_INITIAL;
  3846. BapTrace("BAP state change to %s on HCONN 0x%x",
  3847. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3848. }
  3849. }
  3850. /*
  3851. Returns:
  3852. void
  3853. Description:
  3854. Called when we know the result of a call attempt. pBcbLocal represents the
  3855. bundle that called out. *pBapCallResult contains information about the call
  3856. attempt.
  3857. */
  3858. VOID
  3859. BapEventCallResult(
  3860. IN BCB* pBcbLocal,
  3861. IN BAP_CALL_RESULT* pBapCallResult
  3862. )
  3863. {
  3864. BAPCB* pBapCbLocal;
  3865. BAP_STATE* pBapState;
  3866. DWORD dwResult;
  3867. HPORT hPort;
  3868. PCB* pPcbNew;
  3869. PPP_MESSAGE PppMsg;
  3870. BOOL fWillCallAgain;
  3871. PPP_ASSERT(NULL != pBcbLocal);
  3872. PPP_ASSERT(NULL != pBapCallResult);
  3873. pBapCbLocal = &(pBcbLocal->BapCb);
  3874. pBapState = &(pBapCbLocal->BapState);
  3875. dwResult = pBapCallResult->dwResult;
  3876. // If we have to use pbPhoneDeltaRemote, it had better not be NULL
  3877. PPP_ASSERT(!pBapCbLocal->fPeerSuppliedPhoneNumber ||
  3878. (NULL != pBapCbLocal->pbPhoneDeltaRemote));
  3879. PPP_ASSERT(BAP_STATE_LIMIT >= *pBapState);
  3880. // The call failed, but we have other numbers to try
  3881. fWillCallAgain = (0 != dwResult) &&
  3882. pBapCbLocal->fPeerSuppliedPhoneNumber &&
  3883. (NULL != pBapCbLocal->pbPhoneDeltaRemote) &&
  3884. (0 !=
  3885. pBapCbLocal->pbPhoneDeltaRemote[pBapCbLocal->dwPhoneDeltaRemoteOffset]);
  3886. BapTrace("BapEventCallResult (%s) on HCONN 0x%x",
  3887. dwResult ? "failure" : "success",
  3888. pBcbLocal->hConnection);
  3889. *pBapState = BAP_STATE_INITIAL;
  3890. BapTrace("BAP state change to %s on HCONN 0x%x",
  3891. SzBapStateName[*pBapState],
  3892. pBcbLocal->hConnection);
  3893. pBapCbLocal->dwType = BAP_PACKET_STATUS_IND;
  3894. pBapCbLocal->dwOptions = BAP_N_CALL_STATUS;
  3895. pBapCbLocal->dwStatus = dwResult ? 255 : 0;
  3896. pBapCbLocal->dwAction = fWillCallAgain;
  3897. if (FSendInitialBapRequest(pBcbLocal))
  3898. {
  3899. *pBapState = BAP_STATE_SENT_STATUS_IND;
  3900. BapTrace("BAP state change to %s on HCONN 0x%x",
  3901. SzBapStateName[*pBapState], pBcbLocal->hConnection);
  3902. // BapEventRecvStatusResp or BapEventTimeout will get called at some
  3903. // point, and we will free pBapCbLocal->pbPhoneDeltaRemote.
  3904. }
  3905. else
  3906. {
  3907. if (NULL != pBapCbLocal->pbPhoneDeltaRemote)
  3908. {
  3909. LOCAL_FREE(pBapCbLocal->pbPhoneDeltaRemote);
  3910. }
  3911. pBapCbLocal->pbPhoneDeltaRemote = NULL;
  3912. }
  3913. if (0 == dwResult)
  3914. {
  3915. if ((HRASCONN)-1 != pBapCallResult->hRasConn)
  3916. {
  3917. CHAR* psz[3];
  3918. // hRasConn will be -1 if we are here because of a message from Ddm,
  3919. // not RasDial().
  3920. hPort = RasGetHport(pBapCallResult->hRasConn);
  3921. pPcbNew = GetPCBPointerFromhPort(hPort);
  3922. if (NULL == pPcbNew)
  3923. {
  3924. BapTrace("BapEventCallResult: No PCB for new port %d in "
  3925. "HCONN 0x%x!",
  3926. hPort, pBcbLocal->hConnection);
  3927. return;
  3928. }
  3929. psz[0] = pPcbNew->pBcb->szLocalUserName;
  3930. psz[1] = pPcbNew->pBcb->szEntryName;
  3931. psz[2] = pPcbNew->szPortName;
  3932. PppLogInformation(ROUTERLOG_BAP_CLIENT_CONNECTED, 3, psz);
  3933. if ((ROUTER_IF_TYPE_FULL_ROUTER ==
  3934. pPcbNew->pBcb->InterfaceInfo.IfType))
  3935. {
  3936. // Inform Ddm that a new link is up. This allows MprAdmin, for
  3937. // example, to display Active Connections correctly.
  3938. ZeroMemory(&PppMsg, sizeof(PppMsg));
  3939. PppMsg.hPort = hPort;
  3940. PppMsg.dwMsgId = PPPDDMMSG_NewBapLinkUp;
  3941. PppMsg.ExtraInfo.BapNewLinkUp.hRasConn =
  3942. pBapCallResult->hRasConn;
  3943. PppConfigInfo.SendPPPMessageToDdm(&PppMsg);
  3944. }
  3945. }
  3946. }
  3947. }