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.

962 lines
27 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. if (!(pAtcpConn->Flags & ATCP_CONNECTION_CLOSING))
  280. {
  281. fKill = TRUE;
  282. pAtcpConn->Flags |= ATCP_CONNECTION_CLOSING;
  283. }
  284. }
  285. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  286. if (!fKill)
  287. {
  288. return;
  289. }
  290. // and remove from the list
  291. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  292. RemoveEntryList(&pAtcpConn->Linkage);
  293. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  294. // free that memory
  295. AtalkFreeMemory(pAtcpConn);
  296. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  297. ("DerefPPPConn: PPP connection %lx freed\n",pAtcpConn));
  298. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  299. PPPConnections--;
  300. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  301. // if possible (i.e. if this was the last connection), unlock PPP pages
  302. AtalkUnlockPPPIfNecessary();
  303. }
  304. //***
  305. //
  306. // Function: FindAndRefPPPConnByAddr
  307. // Finds the corresponding connection element, given the network
  308. // address (of the remote client)
  309. //
  310. // Parameters: destNode - network addr of the destination (remote client)
  311. // pdwFlags - pointer to a dword to return Flags field
  312. //
  313. // Return: pointer to the corresponding connection element, if found
  314. //
  315. //***$
  316. PATCPCONN
  317. FindAndRefPPPConnByAddr(
  318. IN ATALK_NODEADDR destNode,
  319. OUT DWORD *pdwFlags
  320. )
  321. {
  322. PATCPCONN pAtcpConn=NULL;
  323. PATCPCONN pAtcpWalker;
  324. PLIST_ENTRY pList;
  325. KIRQL OldIrql;
  326. // RAS not configured?
  327. if (!RasPortDesc)
  328. {
  329. return(NULL);
  330. }
  331. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  332. if (!(RasPortDesc->pd_Flags & PD_ACTIVE))
  333. {
  334. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  335. ("FindAndRefPPPConnByAddr: RAS not active, ignoring\n"));
  336. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  337. return(NULL);
  338. }
  339. pList = RasPortDesc->pd_PPPConnHead.Flink;
  340. //
  341. // walk through all the PPP clients to see if we find ours
  342. //
  343. while (pList != &RasPortDesc->pd_PPPConnHead)
  344. {
  345. pAtcpWalker = CONTAINING_RECORD(pList, ATCPCONN, Linkage);
  346. pList = pAtcpWalker->Linkage.Flink;
  347. ACQUIRE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock);
  348. if (ATALK_NODES_EQUAL(&pAtcpWalker->NetAddr, &destNode))
  349. {
  350. pAtcpConn = pAtcpWalker;
  351. pAtcpConn->RefCount++;
  352. *pdwFlags = pAtcpWalker->Flags;
  353. RELEASE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock);
  354. break;
  355. }
  356. RELEASE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock);
  357. }
  358. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  359. return( pAtcpConn );
  360. }
  361. //***
  362. //
  363. // Function: PPPRoutePacketToWan
  364. // This routine picks up a packet from the lan, checks to see if
  365. // it must be forwarded to any of the PPP clients and does the
  366. // good deed.
  367. //
  368. // Parameters: pDestAddr - who is this packet addressed to? (potentially bcast)
  369. // pSrcAddr - who sent this packet
  370. // Protocol - what packet is it? (ATP, NBP, etc.)
  371. // packet - buffer containing the packet
  372. // PktLen - how big is the packet
  373. // broadcast - is this a broadcast packet?
  374. // pDelivered - set on return: did we forward it to any dial-in
  375. // client (set to TRUE only for directed dgrams)
  376. //
  377. // Return: none
  378. //
  379. //***$
  380. VOID
  381. PPPRoutePacketToWan(
  382. IN ATALK_ADDR *pDestAddr,
  383. IN ATALK_ADDR *pSrcAddr,
  384. IN BYTE Protocol,
  385. IN PBYTE packet,
  386. IN USHORT PktLen,
  387. IN USHORT HopCount,
  388. IN BOOLEAN broadcast,
  389. OUT PBOOLEAN pDelivered
  390. )
  391. {
  392. KIRQL OldIrql;
  393. PATCPCONN pAtcpConn;
  394. PATCPCONN pPrevAtcpConn;
  395. PLIST_ENTRY pConnList;
  396. ATALK_NODEADDR DestNode;
  397. ATALK_NODEADDR SourceNode;
  398. DWORD StatusCode;
  399. DWORD dwFlags;
  400. BOOLEAN fRtmpPacket=FALSE;
  401. DBG_PPP_CHECK_PAGED_CODE();
  402. // assume for now
  403. *pDelivered = FALSE;
  404. //
  405. // if this is a unicast, see if a PPP client with this dest address exists
  406. //
  407. if (!broadcast)
  408. {
  409. DestNode.atn_Network = pDestAddr->ata_Network;
  410. DestNode.atn_Node = pDestAddr->ata_Node;
  411. // first and foremost, let's find the puppy
  412. pAtcpConn = FindAndRefPPPConnByAddr(DestNode, &dwFlags);
  413. if (pAtcpConn == NULL)
  414. {
  415. return;
  416. }
  417. // let the caller know that we found who this data was meant for
  418. *pDelivered = TRUE;
  419. // if this dude isn't ready to route data, drop this packet!
  420. if (!(dwFlags & ATCP_CONNECTION_UP))
  421. {
  422. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  423. ("PPPRoutePacketToWan: dropping pkt on %lx, line-up not done\n",pAtcpConn));
  424. // remove the refcount put in by FindAndRefPPPConnByAddr
  425. DerefPPPConn(pAtcpConn);
  426. return;
  427. }
  428. // send the packet out
  429. PPPTransmit(pAtcpConn,
  430. pDestAddr,
  431. pSrcAddr,
  432. Protocol,
  433. packet,
  434. PktLen,
  435. HopCount);
  436. // remove the refcount put in by FindAndRefPPPConnByAddr
  437. DerefPPPConn(pAtcpConn);
  438. return;
  439. }
  440. //
  441. // it's a broadcast packet: must send it to all the PPP guys
  442. //
  443. if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_RTMPRESPONSEORDATA)
  444. {
  445. fRtmpPacket = TRUE;
  446. }
  447. pAtcpConn = NULL;
  448. pPrevAtcpConn = NULL;
  449. SourceNode.atn_Network = pSrcAddr->ata_Network;
  450. SourceNode.atn_Node = pSrcAddr->ata_Node;
  451. while (1)
  452. {
  453. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  454. //
  455. // first, let's find the right connection to work on
  456. //
  457. while (1)
  458. {
  459. // if we're in the middle of the list, get to the next guy
  460. if (pAtcpConn != NULL)
  461. {
  462. pConnList = pAtcpConn->Linkage.Flink;
  463. }
  464. // we're just starting: get the guy at the head of the list
  465. else
  466. {
  467. pConnList = RasPortDesc->pd_PPPConnHead.Flink;
  468. }
  469. // finished all?
  470. if (pConnList == &RasPortDesc->pd_PPPConnHead)
  471. {
  472. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  473. if (pPrevAtcpConn)
  474. {
  475. DerefPPPConn(pPrevAtcpConn);
  476. }
  477. return;
  478. }
  479. pAtcpConn = CONTAINING_RECORD(pConnList, ATCPCONN, Linkage);
  480. ACQUIRE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  481. // if this guy sent out the broadcast, don't send it back to him!
  482. if (ATALK_NODES_EQUAL(&pAtcpConn->NetAddr, &SourceNode))
  483. {
  484. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  485. ("PPPRoutePacketToWan: skipping bcast from source\n"));
  486. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  487. continue;
  488. }
  489. // if this dude isn't ready to route data, skip
  490. if (!(pAtcpConn->Flags & ATCP_CONNECTION_UP))
  491. {
  492. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  493. ("PPPRoutePacketToWan: skipping %lx because line-up not done\n",pAtcpConn));
  494. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  495. continue;
  496. }
  497. //
  498. // if this is an RTMP packet and the client doesn't want those
  499. // packets, don't send
  500. //
  501. if (fRtmpPacket && (pAtcpConn->Flags & ATCP_SUPPRESS_RTMP))
  502. {
  503. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  504. ("PPPRoutePacketToWan: skipping %lx because RTMP data to be suppressed\n",pAtcpConn));
  505. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  506. continue;
  507. }
  508. // if this dude wants all broadcasts suppressed, skip it
  509. if (pAtcpConn->Flags & ATCP_SUPPRESS_ALLBCAST)
  510. {
  511. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  512. ("PPPRoutePacketToWan: skipping %lx because all bcast to be suppressed\n",pAtcpConn));
  513. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  514. continue;
  515. }
  516. // let's make sure this connection stays around till we finish
  517. pAtcpConn->RefCount++;
  518. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  519. break;
  520. }
  521. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  522. //
  523. // remove the refcount on the previous connection we put in earlier
  524. //
  525. if (pPrevAtcpConn)
  526. {
  527. DerefPPPConn(pPrevAtcpConn);
  528. }
  529. ASSERT(pPrevAtcpConn != pAtcpConn);
  530. pPrevAtcpConn = pAtcpConn;
  531. PPPTransmit(pAtcpConn,
  532. pDestAddr,
  533. pSrcAddr,
  534. Protocol,
  535. packet,
  536. PktLen,
  537. HopCount);
  538. }
  539. }
  540. //***
  541. //
  542. // Function: PPPTransmit
  543. // This routine sends the packet out to a PPP destination
  544. //
  545. // Parameters: pAtcpConn - PPP connection to send to
  546. // pDestAddr - who is this packet addressed to? (potentially bcast)
  547. // pSrcAddr - who sent this packet
  548. // Protocol - what packet is it? (ATP, NBP, etc.)
  549. // packet - buffer containing the packet
  550. // PktLen - how big is the packet
  551. // HopCount - hopcount in the DDP pkt as received
  552. //
  553. // Return: none
  554. //
  555. //***$
  556. VOID FASTCALL
  557. PPPTransmit(
  558. IN PATCPCONN pAtcpConn,
  559. IN ATALK_ADDR *pDestAddr,
  560. IN ATALK_ADDR *pSrcAddr,
  561. IN BYTE Protocol,
  562. IN PBYTE packet,
  563. IN USHORT PktLen,
  564. IN USHORT HopCount
  565. )
  566. {
  567. PBUFFER_DESC pBufCopy;
  568. PBUFFER_DESC pPktDesc;
  569. SEND_COMPL_INFO SendInfo;
  570. PBYTE pLinkDdpOptHdr;
  571. PBYTE pDgram;
  572. ATALK_ERROR error;
  573. DBG_PPP_CHECK_PAGED_CODE();
  574. // allocate a buffer and bufdesc to copy the incoming packet (data portion)
  575. pBufCopy = AtalkAllocBuffDesc(NULL,PktLen,(BD_FREE_BUFFER | BD_CHAR_BUFFER));
  576. if (pBufCopy == NULL)
  577. {
  578. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  579. ("PPPTransmit: alloc BufDesc failed\n"));
  580. return;
  581. }
  582. // copy the data in
  583. AtalkCopyBufferToBuffDesc(packet, PktLen, pBufCopy, 0);
  584. // allocate a buffdesc to hold headers
  585. AtalkNdisAllocBuf(&pPktDesc);
  586. if (pPktDesc == NULL)
  587. {
  588. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  589. ("PPPTransmit: couldn't alloc ndis bufdesc\n"));
  590. AtalkFreeBuffDesc(pBufCopy);
  591. return;
  592. }
  593. // put in the Mac header (NdisWan's header)
  594. pLinkDdpOptHdr = pPktDesc->bd_CharBuffer;
  595. AtalkNdisBuildPPPPHdr(pLinkDdpOptHdr, pAtcpConn);
  596. // make up the DDP header
  597. pDgram = pLinkDdpOptHdr + WAN_LINKHDR_LEN;
  598. *pDgram++ = (DDP_HOP_COUNT(HopCount) + DDP_MSB_LEN(PktLen + LDDP_HDR_LEN));
  599. PUTSHORT2BYTE(pDgram, (PktLen + LDDP_HDR_LEN));
  600. pDgram++;
  601. PUTSHORT2SHORT(pDgram, 0);
  602. pDgram += sizeof(USHORT);
  603. PUTSHORT2SHORT(pDgram, pDestAddr->ata_Network);
  604. pDgram += sizeof(USHORT);
  605. PUTSHORT2SHORT(pDgram, pSrcAddr->ata_Network);
  606. pDgram += sizeof(USHORT);
  607. *pDgram++ = pDestAddr->ata_Node;
  608. *pDgram++ = pSrcAddr->ata_Node;
  609. *pDgram++ = pDestAddr->ata_Socket;
  610. *pDgram++ = pSrcAddr->ata_Socket;
  611. *pDgram++ = Protocol;
  612. // Set length in the buffer descriptor.
  613. AtalkSetSizeOfBuffDescData(pPktDesc, WAN_LINKHDR_LEN + LDDP_HDR_LEN);
  614. // chain in this bufdesc
  615. AtalkPrependBuffDesc(pPktDesc, pBufCopy);
  616. INTERLOCKED_ADD_STATISTICS(&RasPortDesc->pd_PortStats.prtst_DataOut,
  617. AtalkSizeBuffDesc(pPktDesc),
  618. &AtalkStatsLock.SpinLock);
  619. // set up our completion info
  620. SendInfo.sc_TransmitCompletion = PPPTransmitCompletion;
  621. SendInfo.sc_Ctx1 = RasPortDesc;
  622. SendInfo.sc_Ctx2 = pBufCopy;
  623. SendInfo.sc_Ctx3 = pAtcpConn;
  624. // send the packet
  625. error = AtalkNdisSendPacket(RasPortDesc,
  626. pPktDesc,
  627. AtalkDdpSendComplete,
  628. &SendInfo);
  629. if (!ATALK_SUCCESS(error))
  630. {
  631. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  632. ("PPPTransmit: AtalkNdisSendPacket failed %ld\n",error));
  633. AtalkDdpSendComplete(NDIS_STATUS_FAILURE,
  634. pPktDesc,
  635. &SendInfo);
  636. }
  637. }
  638. //***
  639. //
  640. // Function: PPPTransmitCompletion
  641. // This is the completion routine for PPPTransmit, and is called
  642. // by NDIS after the packet is sent out (or failure occurs)
  643. //
  644. // Parameters: Status - how did the send go
  645. // pSendInfo - completion info
  646. //
  647. // Return: none
  648. //
  649. //***$
  650. VOID FASTCALL
  651. PPPTransmitCompletion(
  652. IN NDIS_STATUS Status,
  653. IN PSEND_COMPL_INFO pSendInfo
  654. )
  655. {
  656. PBUFFER_DESC pBuffDesc;
  657. DBG_PPP_CHECK_PAGED_CODE();
  658. pBuffDesc = (PBUFFER_DESC)(pSendInfo->sc_Ctx2);
  659. ASSERT(pBuffDesc != NULL);
  660. ASSERT(pBuffDesc->bd_Flags & (BD_CHAR_BUFFER | BD_FREE_BUFFER));
  661. if (Status != 0)
  662. {
  663. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  664. ("PPPTransmitCompletion: send failed, %lx on %lx\n",
  665. Status,pSendInfo->sc_Ctx3));
  666. }
  667. AtalkFreeBuffDesc(pBuffDesc);
  668. }
  669. //***
  670. //
  671. // Function: PPPGetDynamicAddr
  672. // This routine gets a network address for a PPP dial-in client.
  673. // It does the same AARP logic as if it were acquiring a
  674. // node-address for the host itself.
  675. //
  676. // Parameters: pAtcpConn - the connection for which we need a network addr
  677. //
  678. // Return: ARAPERR_NO_ERROR if all went well.
  679. //
  680. //***$
  681. DWORD
  682. PPPGetDynamicAddr(
  683. IN PATCPCONN pAtcpConn
  684. )
  685. {
  686. ATALK_NODEADDR NetAddr;
  687. ATALK_NETWORKRANGE NetRange;
  688. BOOLEAN fFound=FALSE;
  689. KIRQL OldIrql;
  690. DWORD StatusCode=ARAPERR_STACK_NOT_UP;
  691. DBG_PPP_CHECK_PAGED_CODE();
  692. ASSERT(AtalkDefaultPort != NULL);
  693. //
  694. // go find a node address on the default port (we'll never get this far if
  695. // default port isn't up yet)
  696. //
  697. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  698. ASSERT(!(pAtcpConn->Flags & ATCP_FINDING_NODE));
  699. pAtcpConn->Flags |= ATCP_FINDING_NODE;
  700. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  701. AtalkLockInitIfNecessary();
  702. // if we are stuck in the startup range, use that range for dial-in guys, too
  703. if (WITHIN_NETWORK_RANGE(AtalkDefaultPort->pd_NetworkRange.anr_LastNetwork,
  704. &AtalkStartupNetworkRange))
  705. {
  706. NetRange = AtalkStartupNetworkRange;
  707. }
  708. else
  709. {
  710. NetRange = AtalkDefaultPort->pd_NetworkRange;
  711. }
  712. fFound = AtalkInitAarpForNodeInRange(AtalkDefaultPort,
  713. (PVOID)pAtcpConn,
  714. TRUE,
  715. NetRange,
  716. &NetAddr);
  717. AtalkUnlockInitIfNecessary();
  718. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  719. pAtcpConn->Flags &= ~ATCP_FINDING_NODE;
  720. if (fFound)
  721. {
  722. // store that adddr!
  723. pAtcpConn->NetAddr.atn_Network = NetAddr.atn_Network;
  724. pAtcpConn->NetAddr.atn_Node = NetAddr.atn_Node;
  725. pAtcpConn->Flags |= ATCP_NODE_IN_USE;
  726. StatusCode = ARAPERR_NO_ERROR;
  727. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  728. ("PPPGetDynamicAddr: found addr for PPP client = %lx %lx\n",
  729. NetAddr.atn_Network,NetAddr.atn_Node));
  730. }
  731. else
  732. {
  733. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  734. ("ArapGetDynamicAddr: PPP: no more network addr left?\n"));
  735. pAtcpConn->Flags &= ~ATCP_NODE_IN_USE;
  736. pAtcpConn->NetAddr.atn_Network = 0;
  737. pAtcpConn->NetAddr.atn_Node = 0;
  738. StatusCode = ARAPERR_NO_NETWORK_ADDR;
  739. }
  740. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  741. return(StatusCode);
  742. }