Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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