Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

959 lines
26 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ppp.c
  5. Abstract:
  6. This module implements routines that are used for PPP functionality
  7. Author:
  8. Shirish Koti
  9. Revision History:
  10. 11 Mar 1998 Initial Version
  11. --*/
  12. #define ARAP_LOCALS
  13. #include <atalk.h>
  14. #pragma hdrstop
  15. #define FILENUM PPP
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE_PPP, AllocPPPConn)
  18. #pragma alloc_text(PAGE_PPP, PPPProcessIoctl)
  19. #pragma alloc_text(PAGE_PPP, PPPRoutePacketToWan)
  20. #pragma alloc_text(PAGE_PPP, PPPTransmit)
  21. #pragma alloc_text(PAGE_PPP, PPPTransmitCompletion)
  22. #pragma alloc_text(PAGE_PPP, DerefPPPConn)
  23. #pragma alloc_text(PAGE_PPP, PPPGetDynamicAddr)
  24. #endif
  25. //***
  26. //
  27. // Function: AllocPPPConn
  28. // Allocate a connection element and initialize fields
  29. //
  30. // Parameters: none
  31. //
  32. // Return: pointer to a newly allocated connection element
  33. //
  34. //***$
  35. PATCPCONN
  36. AllocPPPConn(
  37. IN VOID
  38. )
  39. {
  40. PATCPCONN pAtcpConn;
  41. KIRQL OldIrql;
  42. DBG_PPP_CHECK_PAGED_CODE();
  43. if ( (pAtcpConn = AtalkAllocZeroedMemory(sizeof(ATCPCONN))) == NULL)
  44. {
  45. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("AllocPPPConn: alloc failed\n"));
  46. return(NULL);
  47. }
  48. #if DBG
  49. pAtcpConn->Signature = ATCPCONN_SIGNATURE;
  50. #endif
  51. // RAS refcount
  52. pAtcpConn->RefCount = 1;
  53. pAtcpConn->Flags |= ATCP_DLL_SETUP_DONE;
  54. INITIALIZE_SPIN_LOCK(&pAtcpConn->SpinLock);
  55. KeInitializeEvent(&pAtcpConn->NodeAcquireEvent, NotificationEvent, FALSE);
  56. // and insert it in the list
  57. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  58. InsertTailList(&RasPortDesc->pd_PPPConnHead, &pAtcpConn->Linkage);
  59. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  60. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  61. PPPConnections++;
  62. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  63. return( pAtcpConn );
  64. }
  65. //***
  66. //
  67. // Function: PPPProcessIoctl
  68. // This routine gets called in to process ioclts coming from ATCP
  69. // For SETUP, we allocate a connection context, get an address for
  70. // the client, get the zone and router info.
  71. // For CLOSE, we mark and dereference our connection context
  72. //
  73. // Parameters: pIrp - irp from ATCP
  74. // pSndRcvInfo - buffer from ATCP that contains all the info
  75. // IoControlCode - what does ATCP want to do
  76. //
  77. // Return: none
  78. //
  79. //***$
  80. NTSTATUS FASTCALL
  81. PPPProcessIoctl(
  82. IN PIRP pIrp,
  83. IN OUT PARAP_SEND_RECV_INFO pSndRcvInfo,
  84. IN ULONG IoControlCode,
  85. IN PATCPCONN pIncomingAtcpConn
  86. )
  87. {
  88. KIRQL OldIrql;
  89. PATCPINFO pAtcpInfo;
  90. PATCPCONN pAtcpConn;
  91. DWORD dwRetCode=ARAPERR_NO_ERROR;
  92. PATCP_SUPPRESS_INFO pSupprInfo;
  93. ATALK_NODEADDR ClientNode;
  94. DWORD DataLen=0;
  95. DWORD ErrCode;
  96. BOOLEAN fDerefPort=FALSE;
  97. NTSTATUS ReturnStatus=STATUS_SUCCESS;
  98. DBG_PPP_CHECK_PAGED_CODE();
  99. pAtcpConn = pIncomingAtcpConn;
  100. switch (IoControlCode)
  101. {
  102. case IOCTL_ATCP_SETUP_CONNECTION:
  103. ErrCode = ATALK_PORT_INVALID;
  104. // put a IrpProcess refcount, so AtalkDefaultPort doesn't go away in PnP
  105. if (!AtalkReferenceDefaultPort())
  106. {
  107. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  108. ("PPPProcessIoctl: Default port gone, or going %lx not accepted (%lx)\n", pIrp,IoControlCode));
  109. dwRetCode = ARAPERR_STACK_IS_NOT_ACTIVE;
  110. break;
  111. }
  112. fDerefPort = TRUE;
  113. // allocate connection context
  114. pAtcpConn = AllocPPPConn();
  115. if (!pAtcpConn)
  116. {
  117. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  118. ("PPPProcessIoctl: alloc failed\n"));
  119. pSndRcvInfo->StatusCode = ARAPERR_OUT_OF_RESOURCES;
  120. break;
  121. }
  122. pAtcpConn->pDllContext = pSndRcvInfo->pDllContext;
  123. dwRetCode = PPPGetDynamicAddr(pAtcpConn);
  124. if (dwRetCode != ARAPERR_NO_ERROR)
  125. {
  126. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  127. ("PPPProcessIoctl: couldn't get network addr %ld (%lx)\n",
  128. dwRetCode,pAtcpConn));
  129. dwRetCode = ARAPERR_NO_NETWORK_ADDR;
  130. // remove the creation refcount
  131. DerefPPPConn(pAtcpConn);
  132. break;
  133. }
  134. pAtcpInfo = (PATCPINFO)&pSndRcvInfo->Data[0];
  135. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  136. ACQUIRE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
  137. if ((AtalkDefaultPort->pd_Flags & PD_PNP_RECONFIGURE) ||
  138. (AtalkDefaultPort->pd_Flags & PD_CLOSING))
  139. {
  140. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  141. ("PPPProcessIoctl: PnP is ine progress\n"));
  142. dwRetCode = ARAPERR_STACK_IS_NOT_ACTIVE;
  143. RELEASE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
  144. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  145. // remove the creation refcount
  146. DerefPPPConn(pAtcpConn);
  147. break;
  148. }
  149. // we will be returning server's address and router's address
  150. DataLen += (2*sizeof(NET_ADDR));
  151. // copy server's net address
  152. pAtcpInfo->ServerAddr.ata_Network =
  153. AtalkDefaultPort->pd_Nodes->an_NodeAddr.atn_Network;
  154. pAtcpInfo->ServerAddr.ata_Node =
  155. AtalkDefaultPort->pd_Nodes->an_NodeAddr.atn_Node;
  156. // if we are a router, copy our own address
  157. if (AtalkDefaultPort->pd_Flags & PD_ROUTER_RUNNING)
  158. {
  159. pAtcpInfo->DefaultRouterAddr.ata_Network =
  160. AtalkDefaultPort->pd_RouterNode->an_NodeAddr.atn_Network;
  161. pAtcpInfo->DefaultRouterAddr.ata_Network =
  162. AtalkDefaultPort->pd_RouterNode->an_NodeAddr.atn_Node;
  163. }
  164. // if we know who the router on the net is, copy his address
  165. else if (AtalkDefaultPort->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  166. {
  167. pAtcpInfo->DefaultRouterAddr.ata_Network =
  168. AtalkDefaultPort->pd_ARouter.atn_Network;
  169. pAtcpInfo->DefaultRouterAddr.ata_Node =
  170. AtalkDefaultPort->pd_ARouter.atn_Node;
  171. }
  172. // hmmm: no router!
  173. else
  174. {
  175. pAtcpInfo->DefaultRouterAddr.ata_Network = 0;
  176. pAtcpInfo->DefaultRouterAddr.ata_Node = 0;
  177. }
  178. //
  179. // copy the name of the zone on which this server lives
  180. //
  181. if (AtalkDesiredZone)
  182. {
  183. pAtcpInfo->ServerZoneName[0] = AtalkDesiredZone->zn_ZoneLen;
  184. RtlCopyMemory( &pAtcpInfo->ServerZoneName[1],
  185. &AtalkDesiredZone->zn_Zone[0],
  186. AtalkDesiredZone->zn_ZoneLen );
  187. }
  188. else if (AtalkDefaultPort->pd_DefaultZone)
  189. {
  190. pAtcpInfo->ServerZoneName[0] =
  191. AtalkDefaultPort->pd_DefaultZone->zn_ZoneLen;
  192. RtlCopyMemory( &pAtcpInfo->ServerZoneName[1],
  193. &AtalkDefaultPort->pd_DefaultZone->zn_Zone[0],
  194. AtalkDefaultPort->pd_DefaultZone->zn_ZoneLen );
  195. }
  196. else
  197. {
  198. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  199. ("PPPProcessIoctl: Server not in any zone!!\n"));
  200. pAtcpInfo->ServerZoneName[0] = 0;
  201. }
  202. RELEASE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
  203. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  204. DataLen += pAtcpInfo->ServerZoneName[0];
  205. // return our context and the network addr to the dll
  206. pSndRcvInfo->AtalkContext = pAtcpConn;
  207. pSndRcvInfo->ClientAddr.ata_Network = pAtcpConn->NetAddr.atn_Network;
  208. pSndRcvInfo->ClientAddr.ata_Node = pAtcpConn->NetAddr.atn_Node;
  209. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  210. ("PPPProcessIoctl: PPP conn %lx created, addr = %x.%x\n",
  211. pAtcpConn,pSndRcvInfo->ClientAddr.ata_Network,pSndRcvInfo->ClientAddr.ata_Node));
  212. break;
  213. case IOCTL_ATCP_SUPPRESS_BCAST:
  214. pSupprInfo = (PATCP_SUPPRESS_INFO)&pSndRcvInfo->Data[0];
  215. //
  216. // see what flags need to be set: suppress only RTMP only or all bcast
  217. //
  218. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  219. if (pSupprInfo->SuppressRtmp)
  220. {
  221. pAtcpConn->Flags |= ATCP_SUPPRESS_RTMP;
  222. }
  223. if (pSupprInfo->SuppressAllBcast)
  224. {
  225. pAtcpConn->Flags |= ATCP_SUPPRESS_ALLBCAST;
  226. }
  227. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  228. break;
  229. case IOCTL_ATCP_CLOSE_CONNECTION:
  230. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  231. ("PPPProcessIoctl: close connection received on %lx (refcount %d)\n",
  232. pAtcpConn,pAtcpConn->RefCount));
  233. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  234. pAtcpConn->Flags &= ~(ATCP_CONNECTION_UP | ATCP_DLL_SETUP_DONE);
  235. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  236. // PPP wants to close connection: take away the RAS refcount
  237. DerefPPPConn(pAtcpConn);
  238. break;
  239. default:
  240. ASSERT(0);
  241. break;
  242. }
  243. pSndRcvInfo->DataLen = DataLen;
  244. pSndRcvInfo->StatusCode = dwRetCode;
  245. // complete that irp
  246. ARAP_COMPLETE_IRP(pIrp, (sizeof(ARAP_SEND_RECV_INFO)+DataLen), STATUS_SUCCESS, &ReturnStatus);
  247. if (fDerefPort)
  248. {
  249. // remove that IrpProcess refcount
  250. AtalkPortDereference(AtalkDefaultPort);
  251. }
  252. return ReturnStatus;
  253. }
  254. //***
  255. //
  256. // Function: DerefPPPConn
  257. // Decrements the refcount of the connection element by 1. If the
  258. // refcount goes to 0, releases network addr and frees it
  259. //
  260. // Parameters: pAtcpConn - connection element in question
  261. //
  262. // Return: none
  263. //
  264. //***$
  265. VOID
  266. DerefPPPConn(
  267. IN PATCPCONN pAtcpConn
  268. )
  269. {
  270. KIRQL OldIrql;
  271. BOOLEAN fKill = FALSE;
  272. DBG_PPP_CHECK_PAGED_CODE();
  273. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  274. ASSERT(pAtcpConn->Signature == ATCPCONN_SIGNATURE);
  275. ASSERT(pAtcpConn->RefCount > 0);
  276. pAtcpConn->RefCount--;
  277. if (pAtcpConn->RefCount == 0)
  278. {
  279. fKill = TRUE;
  280. pAtcpConn->Flags |= ATCP_CONNECTION_CLOSING;
  281. }
  282. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  283. if (!fKill)
  284. {
  285. return;
  286. }
  287. // and remove from the list
  288. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  289. RemoveEntryList(&pAtcpConn->Linkage);
  290. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  291. // free that memory
  292. AtalkFreeMemory(pAtcpConn);
  293. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  294. ("DerefPPPConn: PPP connection %lx freed\n",pAtcpConn));
  295. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  296. PPPConnections--;
  297. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  298. // if possible (i.e. if this was the last connection), unlock PPP pages
  299. AtalkUnlockPPPIfNecessary();
  300. }
  301. //***
  302. //
  303. // Function: FindAndRefPPPConnByAddr
  304. // Finds the corresponding connection element, given the network
  305. // address (of the remote client)
  306. //
  307. // Parameters: destNode - network addr of the destination (remote client)
  308. // pdwFlags - pointer to a dword to return Flags field
  309. //
  310. // Return: pointer to the corresponding connection element, if found
  311. //
  312. //***$
  313. PATCPCONN
  314. FindAndRefPPPConnByAddr(
  315. IN ATALK_NODEADDR destNode,
  316. OUT DWORD *pdwFlags
  317. )
  318. {
  319. PATCPCONN pAtcpConn=NULL;
  320. PATCPCONN pAtcpWalker;
  321. PLIST_ENTRY pList;
  322. KIRQL OldIrql;
  323. // RAS not configured?
  324. if (!RasPortDesc)
  325. {
  326. return(NULL);
  327. }
  328. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  329. if (!(RasPortDesc->pd_Flags & PD_ACTIVE))
  330. {
  331. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  332. ("FindAndRefPPPConnByAddr: RAS not active, ignoring\n"));
  333. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  334. return(NULL);
  335. }
  336. pList = RasPortDesc->pd_PPPConnHead.Flink;
  337. //
  338. // walk through all the PPP clients to see if we find ours
  339. //
  340. while (pList != &RasPortDesc->pd_PPPConnHead)
  341. {
  342. pAtcpWalker = CONTAINING_RECORD(pList, ATCPCONN, Linkage);
  343. pList = pAtcpWalker->Linkage.Flink;
  344. ACQUIRE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock);
  345. if (ATALK_NODES_EQUAL(&pAtcpWalker->NetAddr, &destNode))
  346. {
  347. pAtcpConn = pAtcpWalker;
  348. pAtcpConn->RefCount++;
  349. *pdwFlags = pAtcpWalker->Flags;
  350. RELEASE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock);
  351. break;
  352. }
  353. RELEASE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock);
  354. }
  355. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  356. return( pAtcpConn );
  357. }
  358. //***
  359. //
  360. // Function: PPPRoutePacketToWan
  361. // This routine picks up a packet from the lan, checks to see if
  362. // it must be forwarded to any of the PPP clients and does the
  363. // good deed.
  364. //
  365. // Parameters: pDestAddr - who is this packet addressed to? (potentially bcast)
  366. // pSrcAddr - who sent this packet
  367. // Protocol - what packet is it? (ATP, NBP, etc.)
  368. // packet - buffer containing the packet
  369. // PktLen - how big is the packet
  370. // broadcast - is this a broadcast packet?
  371. // pDelivered - set on return: did we forward it to any dial-in
  372. // client (set to TRUE only for directed dgrams)
  373. //
  374. // Return: none
  375. //
  376. //***$
  377. VOID
  378. PPPRoutePacketToWan(
  379. IN ATALK_ADDR *pDestAddr,
  380. IN ATALK_ADDR *pSrcAddr,
  381. IN BYTE Protocol,
  382. IN PBYTE packet,
  383. IN USHORT PktLen,
  384. IN USHORT HopCount,
  385. IN BOOLEAN broadcast,
  386. OUT PBOOLEAN pDelivered
  387. )
  388. {
  389. KIRQL OldIrql;
  390. PATCPCONN pAtcpConn;
  391. PATCPCONN pPrevAtcpConn;
  392. PLIST_ENTRY pConnList;
  393. ATALK_NODEADDR DestNode;
  394. ATALK_NODEADDR SourceNode;
  395. DWORD StatusCode;
  396. DWORD dwFlags;
  397. BOOLEAN fRtmpPacket=FALSE;
  398. DBG_PPP_CHECK_PAGED_CODE();
  399. // assume for now
  400. *pDelivered = FALSE;
  401. //
  402. // if this is a unicast, see if a PPP client with this dest address exists
  403. //
  404. if (!broadcast)
  405. {
  406. DestNode.atn_Network = pDestAddr->ata_Network;
  407. DestNode.atn_Node = pDestAddr->ata_Node;
  408. // first and foremost, let's find the puppy
  409. pAtcpConn = FindAndRefPPPConnByAddr(DestNode, &dwFlags);
  410. if (pAtcpConn == NULL)
  411. {
  412. return;
  413. }
  414. // let the caller know that we found who this data was meant for
  415. *pDelivered = TRUE;
  416. // if this dude isn't ready to route data, drop this packet!
  417. if (!(dwFlags & ATCP_CONNECTION_UP))
  418. {
  419. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  420. ("PPPRoutePacketToWan: dropping pkt on %lx, line-up not done\n",pAtcpConn));
  421. // remove the refcount put in by FindAndRefPPPConnByAddr
  422. DerefPPPConn(pAtcpConn);
  423. return;
  424. }
  425. // send the packet out
  426. PPPTransmit(pAtcpConn,
  427. pDestAddr,
  428. pSrcAddr,
  429. Protocol,
  430. packet,
  431. PktLen,
  432. HopCount);
  433. // remove the refcount put in by FindAndRefPPPConnByAddr
  434. DerefPPPConn(pAtcpConn);
  435. return;
  436. }
  437. //
  438. // it's a broadcast packet: must send it to all the PPP guys
  439. //
  440. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_RTMPRESPONSEORDATA)
  441. {
  442. fRtmpPacket = TRUE;
  443. }
  444. pAtcpConn = NULL;
  445. pPrevAtcpConn = NULL;
  446. SourceNode.atn_Network = pSrcAddr->ata_Network;
  447. SourceNode.atn_Node = pSrcAddr->ata_Node;
  448. while (1)
  449. {
  450. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  451. //
  452. // first, let's find the right connection to work on
  453. //
  454. while (1)
  455. {
  456. // if we're in the middle of the list, get to the next guy
  457. if (pAtcpConn != NULL)
  458. {
  459. pConnList = pAtcpConn->Linkage.Flink;
  460. }
  461. // we're just starting: get the guy at the head of the list
  462. else
  463. {
  464. pConnList = RasPortDesc->pd_PPPConnHead.Flink;
  465. }
  466. // finished all?
  467. if (pConnList == &RasPortDesc->pd_PPPConnHead)
  468. {
  469. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  470. if (pPrevAtcpConn)
  471. {
  472. DerefPPPConn(pPrevAtcpConn);
  473. }
  474. return;
  475. }
  476. pAtcpConn = CONTAINING_RECORD(pConnList, ATCPCONN, Linkage);
  477. ACQUIRE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  478. // if this guy sent out the broadcast, don't send it back to him!
  479. if (ATALK_NODES_EQUAL(&pAtcpConn->NetAddr, &SourceNode))
  480. {
  481. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  482. ("PPPRoutePacketToWan: skipping bcast from source\n"));
  483. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  484. continue;
  485. }
  486. // if this dude isn't ready to route data, skip
  487. if (!(pAtcpConn->Flags & ATCP_CONNECTION_UP))
  488. {
  489. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  490. ("PPPRoutePacketToWan: skipping %lx because line-up not done\n",pAtcpConn));
  491. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  492. continue;
  493. }
  494. //
  495. // if this is an RTMP packet and the client doesn't want those
  496. // packets, don't send
  497. //
  498. if (fRtmpPacket && (pAtcpConn->Flags & ATCP_SUPPRESS_RTMP))
  499. {
  500. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  501. ("PPPRoutePacketToWan: skipping %lx because RTMP data to be suppressed\n",pAtcpConn));
  502. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  503. continue;
  504. }
  505. // if this dude wants all broadcasts suppressed, skip it
  506. if (pAtcpConn->Flags & ATCP_SUPPRESS_ALLBCAST)
  507. {
  508. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  509. ("PPPRoutePacketToWan: skipping %lx because all bcast to be suppressed\n",pAtcpConn));
  510. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  511. continue;
  512. }
  513. // let's make sure this connection stays around till we finish
  514. pAtcpConn->RefCount++;
  515. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  516. break;
  517. }
  518. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  519. //
  520. // remove the refcount on the previous connection we put in earlier
  521. //
  522. if (pPrevAtcpConn)
  523. {
  524. DerefPPPConn(pPrevAtcpConn);
  525. }
  526. ASSERT(pPrevAtcpConn != pAtcpConn);
  527. pPrevAtcpConn = pAtcpConn;
  528. PPPTransmit(pAtcpConn,
  529. pDestAddr,
  530. pSrcAddr,
  531. Protocol,
  532. packet,
  533. PktLen,
  534. HopCount);
  535. }
  536. }
  537. //***
  538. //
  539. // Function: PPPTransmit
  540. // This routine sends the packet out to a PPP destination
  541. //
  542. // Parameters: pAtcpConn - PPP connection to send to
  543. // pDestAddr - who is this packet addressed to? (potentially bcast)
  544. // pSrcAddr - who sent this packet
  545. // Protocol - what packet is it? (ATP, NBP, etc.)
  546. // packet - buffer containing the packet
  547. // PktLen - how big is the packet
  548. // HopCount - hopcount in the DDP pkt as received
  549. //
  550. // Return: none
  551. //
  552. //***$
  553. VOID FASTCALL
  554. PPPTransmit(
  555. IN PATCPCONN pAtcpConn,
  556. IN ATALK_ADDR *pDestAddr,
  557. IN ATALK_ADDR *pSrcAddr,
  558. IN BYTE Protocol,
  559. IN PBYTE packet,
  560. IN USHORT PktLen,
  561. IN USHORT HopCount
  562. )
  563. {
  564. PBUFFER_DESC pBufCopy;
  565. PBUFFER_DESC pPktDesc;
  566. SEND_COMPL_INFO SendInfo;
  567. PBYTE pLinkDdpOptHdr;
  568. PBYTE pDgram;
  569. ATALK_ERROR error;
  570. DBG_PPP_CHECK_PAGED_CODE();
  571. // allocate a buffer and bufdesc to copy the incoming packet (data portion)
  572. pBufCopy = AtalkAllocBuffDesc(NULL,PktLen,(BD_FREE_BUFFER | BD_CHAR_BUFFER));
  573. if (pBufCopy == NULL)
  574. {
  575. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  576. ("PPPTransmit: alloc BufDesc failed\n"));
  577. return;
  578. }
  579. // copy the data in
  580. AtalkCopyBufferToBuffDesc(packet, PktLen, pBufCopy, 0);
  581. // allocate a buffdesc to hold headers
  582. AtalkNdisAllocBuf(&pPktDesc);
  583. if (pPktDesc == NULL)
  584. {
  585. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  586. ("PPPTransmit: couldn't alloc ndis bufdesc\n"));
  587. AtalkFreeBuffDesc(pBufCopy);
  588. return;
  589. }
  590. // put in the Mac header (NdisWan's header)
  591. pLinkDdpOptHdr = pPktDesc->bd_CharBuffer;
  592. AtalkNdisBuildPPPPHdr(pLinkDdpOptHdr, pAtcpConn);
  593. // make up the DDP header
  594. pDgram = pLinkDdpOptHdr + WAN_LINKHDR_LEN;
  595. *pDgram++ = (DDP_HOP_COUNT(HopCount) + DDP_MSB_LEN(PktLen + LDDP_HDR_LEN));
  596. PUTSHORT2BYTE(pDgram, (PktLen + LDDP_HDR_LEN));
  597. pDgram++;
  598. PUTSHORT2SHORT(pDgram, 0);
  599. pDgram += sizeof(USHORT);
  600. PUTSHORT2SHORT(pDgram, pDestAddr->ata_Network);
  601. pDgram += sizeof(USHORT);
  602. PUTSHORT2SHORT(pDgram, pSrcAddr->ata_Network);
  603. pDgram += sizeof(USHORT);
  604. *pDgram++ = pDestAddr->ata_Node;
  605. *pDgram++ = pSrcAddr->ata_Node;
  606. *pDgram++ = pDestAddr->ata_Socket;
  607. *pDgram++ = pSrcAddr->ata_Socket;
  608. *pDgram++ = Protocol;
  609. // Set length in the buffer descriptor.
  610. AtalkSetSizeOfBuffDescData(pPktDesc, WAN_LINKHDR_LEN + LDDP_HDR_LEN);
  611. // chain in this bufdesc
  612. AtalkPrependBuffDesc(pPktDesc, pBufCopy);
  613. INTERLOCKED_ADD_STATISTICS(&RasPortDesc->pd_PortStats.prtst_DataOut,
  614. AtalkSizeBuffDesc(pPktDesc),
  615. &AtalkStatsLock.SpinLock);
  616. // set up our completion info
  617. SendInfo.sc_TransmitCompletion = PPPTransmitCompletion;
  618. SendInfo.sc_Ctx1 = RasPortDesc;
  619. SendInfo.sc_Ctx2 = pBufCopy;
  620. SendInfo.sc_Ctx3 = pAtcpConn;
  621. // send the packet
  622. error = AtalkNdisSendPacket(RasPortDesc,
  623. pPktDesc,
  624. AtalkDdpSendComplete,
  625. &SendInfo);
  626. if (!ATALK_SUCCESS(error))
  627. {
  628. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  629. ("PPPTransmit: AtalkNdisSendPacket failed %ld\n",error));
  630. AtalkDdpSendComplete(NDIS_STATUS_FAILURE,
  631. pPktDesc,
  632. &SendInfo);
  633. }
  634. }
  635. //***
  636. //
  637. // Function: PPPTransmitCompletion
  638. // This is the completion routine for PPPTransmit, and is called
  639. // by NDIS after the packet is sent out (or failure occurs)
  640. //
  641. // Parameters: Status - how did the send go
  642. // pSendInfo - completion info
  643. //
  644. // Return: none
  645. //
  646. //***$
  647. VOID FASTCALL
  648. PPPTransmitCompletion(
  649. IN NDIS_STATUS Status,
  650. IN PSEND_COMPL_INFO pSendInfo
  651. )
  652. {
  653. PBUFFER_DESC pBuffDesc;
  654. DBG_PPP_CHECK_PAGED_CODE();
  655. pBuffDesc = (PBUFFER_DESC)(pSendInfo->sc_Ctx2);
  656. ASSERT(pBuffDesc != NULL);
  657. ASSERT(pBuffDesc->bd_Flags & (BD_CHAR_BUFFER | BD_FREE_BUFFER));
  658. if (Status != 0)
  659. {
  660. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  661. ("PPPTransmitCompletion: send failed, %lx on %lx\n",
  662. Status,pSendInfo->sc_Ctx3));
  663. }
  664. AtalkFreeBuffDesc(pBuffDesc);
  665. }
  666. //***
  667. //
  668. // Function: PPPGetDynamicAddr
  669. // This routine gets a network address for a PPP dial-in client.
  670. // It does the same AARP logic as if it were acquiring a
  671. // node-address for the host itself.
  672. //
  673. // Parameters: pAtcpConn - the connection for which we need a network addr
  674. //
  675. // Return: ARAPERR_NO_ERROR if all went well.
  676. //
  677. //***$
  678. DWORD
  679. PPPGetDynamicAddr(
  680. IN PATCPCONN pAtcpConn
  681. )
  682. {
  683. ATALK_NODEADDR NetAddr;
  684. ATALK_NETWORKRANGE NetRange;
  685. BOOLEAN fFound=FALSE;
  686. KIRQL OldIrql;
  687. DWORD StatusCode=ARAPERR_STACK_NOT_UP;
  688. DBG_PPP_CHECK_PAGED_CODE();
  689. ASSERT(AtalkDefaultPort != NULL);
  690. //
  691. // go find a node address on the default port (we'll never get this far if
  692. // default port isn't up yet)
  693. //
  694. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  695. ASSERT(!(pAtcpConn->Flags & ATCP_FINDING_NODE));
  696. pAtcpConn->Flags |= ATCP_FINDING_NODE;
  697. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  698. AtalkLockInitIfNecessary();
  699. // if we are stuck in the startup range, use that range for dial-in guys, too
  700. if (WITHIN_NETWORK_RANGE(AtalkDefaultPort->pd_NetworkRange.anr_LastNetwork,
  701. &AtalkStartupNetworkRange))
  702. {
  703. NetRange = AtalkStartupNetworkRange;
  704. }
  705. else
  706. {
  707. NetRange = AtalkDefaultPort->pd_NetworkRange;
  708. }
  709. fFound = AtalkInitAarpForNodeInRange(AtalkDefaultPort,
  710. (PVOID)pAtcpConn,
  711. TRUE,
  712. NetRange,
  713. &NetAddr);
  714. AtalkUnlockInitIfNecessary();
  715. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  716. pAtcpConn->Flags &= ~ATCP_FINDING_NODE;
  717. if (fFound)
  718. {
  719. // store that adddr!
  720. pAtcpConn->NetAddr.atn_Network = NetAddr.atn_Network;
  721. pAtcpConn->NetAddr.atn_Node = NetAddr.atn_Node;
  722. pAtcpConn->Flags |= ATCP_NODE_IN_USE;
  723. StatusCode = ARAPERR_NO_ERROR;
  724. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  725. ("PPPGetDynamicAddr: found addr for PPP client = %lx %lx\n",
  726. NetAddr.atn_Network,NetAddr.atn_Node));
  727. }
  728. else
  729. {
  730. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  731. ("ArapGetDynamicAddr: PPP: no more network addr left?\n"));
  732. pAtcpConn->Flags &= ~ATCP_NODE_IN_USE;
  733. pAtcpConn->NetAddr.atn_Network = 0;
  734. pAtcpConn->NetAddr.atn_Node = 0;
  735. StatusCode = ARAPERR_NO_NETWORK_ADDR;
  736. }
  737. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  738. return(StatusCode);
  739. }