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.

3774 lines
86 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. ddp.c
  5. Abstract:
  6. This module implements the ddp protocol.
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com)
  9. Nikhil Kamkolkar (nikhilk@microsoft.com)
  10. Revision History:
  11. 19 Jun 1992 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #include <atalk.h>
  15. #pragma hdrstop
  16. #define FILENUM DDP
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGEINIT, AtalkDdpInitCloseAddress)
  19. #pragma alloc_text(PAGEINIT, atalkDdpInitCloseComplete)
  20. #pragma alloc_text(PAGEINIT, AtalkInitDdpOpenStaticSockets)
  21. #endif
  22. //
  23. // AtalkDdpOpenAddress()
  24. // This opens a DDP address object and returns a pointer to it in
  25. // DdpAddrObject. The AppletalkSocket is created and will be the
  26. // address of this object.
  27. //
  28. ATALK_ERROR
  29. AtalkDdpOpenAddress(
  30. IN PPORT_DESCRIPTOR pPortDesc,
  31. IN BYTE Socket,
  32. IN OUT PATALK_NODEADDR pDesiredNode OPTIONAL,
  33. IN DDPAO_HANDLER pSktHandler OPTIONAL,
  34. IN PVOID pSktCtx OPTIONAL,
  35. IN BYTE Protocol OPTIONAL,
  36. IN PATALK_DEV_CTX pDevCtx,
  37. OUT PDDP_ADDROBJ * ppDdpAddr
  38. )
  39. /*++
  40. Routine Description:
  41. Arguments:
  42. Return Value:
  43. --*/
  44. {
  45. PATALK_NODE pAtalkNode, pNextNode;
  46. PDDP_ADDROBJ pDdpAddr = NULL;
  47. ATALK_ERROR error = ATALK_NO_ERROR;
  48. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  49. ("AtalkDdpOpenAddress: Opening DDP socket %d on port %lx\n",
  50. Socket, pPortDesc));
  51. do
  52. {
  53. // Verify the Appletalk socket number
  54. if (!IS_VALID_SOCKET(Socket))
  55. {
  56. error = ATALK_SOCKET_INVALID;
  57. break;
  58. }
  59. // Allocate space for the address object
  60. if ((pDdpAddr = AtalkAllocZeroedMemory(sizeof(DDP_ADDROBJ))) == NULL)
  61. {
  62. error = ATALK_RESR_MEM;
  63. break;
  64. }
  65. if (pDesiredNode != NULL)
  66. {
  67. AtalkNodeReferenceByAddr(pPortDesc,
  68. pDesiredNode,
  69. &pAtalkNode,
  70. &error);
  71. if (ATALK_SUCCESS(error))
  72. {
  73. ASSERT(VALID_ATALK_NODE(pAtalkNode));
  74. // try to allocate the socket on this node.
  75. error = atalkDdpAllocSocketOnNode(pPortDesc,
  76. Socket,
  77. pAtalkNode,
  78. pSktHandler,
  79. pSktCtx,
  80. Protocol,
  81. pDevCtx,
  82. pDdpAddr);
  83. // Remove the reference on the node.
  84. AtalkNodeDereference(pAtalkNode);
  85. }
  86. break;
  87. }
  88. else
  89. {
  90. KIRQL OldIrql;
  91. // We can open the socket on any one of our
  92. // nodes.
  93. // We first get the port lock
  94. // Then we go through all the nodes on the port
  95. // reference a node, let go of the port lock
  96. // acquire the node lock, try to open the socket
  97. // on it. If we succeed, we return, else we fail.
  98. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  99. do
  100. {
  101. // Try to get a referenced node. null if no non-closing node found.
  102. AtalkNodeReferenceNextNc(pPortDesc->pd_Nodes, &pAtalkNode, &error);
  103. while (ATALK_SUCCESS(error))
  104. {
  105. // We do not use this node if it is orphaned or if
  106. // it is a router node and we are trying to open a
  107. // user socket (dynamic or non-reserved).
  108. if (((pAtalkNode->an_Flags & (AN_ORPHAN_NODE | AN_ROUTER_NODE)) == 0) ||
  109. ((Socket != UNKNOWN_SOCKET) && (Socket <= LAST_APPLE_RESD_SOCKET)))
  110. {
  111. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  112. // try to allocate the socket on this node. PortLock held!
  113. error = atalkDdpAllocSocketOnNode(pPortDesc,
  114. Socket,
  115. pAtalkNode,
  116. pSktHandler,
  117. pSktCtx,
  118. Protocol,
  119. pDevCtx,
  120. pDdpAddr);
  121. if (ATALK_SUCCESS(error))
  122. {
  123. // Done! Break out of the loop. Remove the ref we added.
  124. AtalkNodeDereference(pAtalkNode);
  125. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  126. break;
  127. }
  128. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  129. }
  130. // Gotta get to the next node.
  131. AtalkNodeReferenceNextNc(pAtalkNode->an_Next, &pNextNode, &error);
  132. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  133. AtalkNodeDereference(pAtalkNode);
  134. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  135. pAtalkNode = pNextNode;
  136. }
  137. } while (FALSE);
  138. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  139. }
  140. } while (FALSE);
  141. if (ATALK_SUCCESS(error))
  142. {
  143. if (ppDdpAddr != NULL)
  144. *ppDdpAddr = pDdpAddr;
  145. }
  146. else
  147. {
  148. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  149. ("AtalkDdpOpenAddress: failed with error %lx\n", error));
  150. if (pDdpAddr)
  151. AtalkFreeMemory(pDdpAddr);
  152. }
  153. return error;
  154. }
  155. ATALK_ERROR
  156. AtalkDdpCleanupAddress(
  157. IN PDDP_ADDROBJ pDdpAddr
  158. )
  159. /*++
  160. Routine Description:
  161. Releases any pending requests on the address.
  162. Arguments:
  163. Return Value:
  164. --*/
  165. {
  166. KIRQL OldIrql;
  167. // Free all pending ddp reads.
  168. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  169. while (!IsListEmpty(&pDdpAddr->ddpao_ReadLinkage))
  170. {
  171. PLIST_ENTRY p;
  172. PDDP_READ pRead;
  173. p = RemoveHeadList(&pDdpAddr->ddpao_ReadLinkage);
  174. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  175. pRead = CONTAINING_RECORD(p, DDP_READ, dr_Linkage);
  176. (*pRead->dr_RcvCmp)(ATALK_FAILURE,
  177. pRead->dr_OpBuf,
  178. 0,
  179. NULL,
  180. pRead->dr_RcvCtx);
  181. AtalkDdpDereference(pDdpAddr);
  182. AtalkFreeMemory(pRead);
  183. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  184. }
  185. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  186. return ATALK_NO_ERROR;
  187. }
  188. ATALK_ERROR
  189. AtalkDdpCloseAddress(
  190. IN PDDP_ADDROBJ pDdpAddr,
  191. IN GENERIC_COMPLETION pCloseCmp OPTIONAL,
  192. IN PVOID pCloseCtx OPTIONAL
  193. )
  194. /*++
  195. Routine Description:
  196. Called to close an open ddp address object. This will complete after all
  197. requests on the object are done/cancelled, and the Appletalk Socket is
  198. closed.
  199. Arguments:
  200. Return Value:
  201. --*/
  202. {
  203. KIRQL OldIrql;
  204. BOOLEAN closing;
  205. BOOLEAN pnpZombie;
  206. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  207. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  208. closing = ((pDdpAddr->ddpao_Flags & DDPAO_CLOSING) != 0) ? TRUE : FALSE;
  209. pnpZombie = ((pDdpAddr->ddpao_Flags & DDPAO_SOCK_PNPZOMBIE) != 0) ? TRUE: FALSE;
  210. ASSERTMSG("DdpAddr is already closing!\n", ((!closing) || pnpZombie));
  211. if (!closing)
  212. {
  213. // Set the closing flag and remember the completion routines.
  214. pDdpAddr->ddpao_Flags |= DDPAO_CLOSING;
  215. pDdpAddr->ddpao_CloseComp = pCloseCmp;
  216. pDdpAddr->ddpao_CloseCtx = pCloseCtx;
  217. }
  218. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  219. if (!closing)
  220. {
  221. // Release any pending reads
  222. AtalkDdpCleanupAddress(pDdpAddr);
  223. AtalkNbpCloseSocket(pDdpAddr);
  224. // Remove reference for the creation
  225. AtalkDdpDereference(pDdpAddr);
  226. }
  227. // is this socket in a zombie state? if so, deref it so it'll get freed
  228. if (pnpZombie)
  229. {
  230. ASSERT(closing == TRUE);
  231. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  232. ("AtalkDdpClose..: zombie addr %lx (%lx) deref'ed\n",
  233. pDdpAddr,pDdpAddr->ddpao_Handler));
  234. AtalkDdpDereference(pDdpAddr);
  235. }
  236. return ATALK_PENDING;
  237. }
  238. ATALK_ERROR
  239. AtalkDdpPnPSuspendAddress(
  240. IN PDDP_ADDROBJ pDdpAddr
  241. )
  242. /*++
  243. Routine Description:
  244. Called to "suspend" an open ddp address object. This is called during PnP,
  245. to "suspend" "external" sockets. The nodes associated with this address are
  246. released (deref'ed) and this socket is cleaned up but kept around because
  247. the client might close it. When the client does close it, it gets freed.
  248. Arguments:
  249. Return Value:
  250. --*/
  251. {
  252. KIRQL OldIrql;
  253. PATALK_NODE pNode = pDdpAddr->ddpao_Node;
  254. BOOLEAN closing;
  255. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  256. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  257. closing = ((pDdpAddr->ddpao_Flags & DDPAO_CLOSING) != 0) ? TRUE : FALSE;
  258. ASSERTMSG("DdpAddr is already closing!\n", !closing);
  259. if (!closing)
  260. {
  261. // Set the closing flag and remember the completion routines.
  262. pDdpAddr->ddpao_Flags |= DDPAO_CLOSING;
  263. // this call is only for external sockets
  264. ASSERT((pDdpAddr->ddpao_Flags & DDPAO_SOCK_INTERNAL) == 0);
  265. pDdpAddr->ddpao_Flags |= DDPAO_SOCK_PNPZOMBIE;
  266. }
  267. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  268. if (!closing)
  269. {
  270. PDDP_ADDROBJ * ppDdpAddr;
  271. int index;
  272. // Release any pending reads
  273. AtalkDdpCleanupAddress(pDdpAddr);
  274. AtalkNbpCloseSocket(pDdpAddr);
  275. ACQUIRE_SPIN_LOCK(&pNode->an_Lock, &OldIrql);
  276. index = HASH_ATALK_ADDR(&pDdpAddr->ddpao_Addr) % NODE_DDPAO_HASH_SIZE;
  277. for (ppDdpAddr = &pNode->an_DdpAoHash[index];
  278. *ppDdpAddr != NULL;
  279. ppDdpAddr = &((*ppDdpAddr)->ddpao_Next))
  280. {
  281. if (*ppDdpAddr == pDdpAddr)
  282. {
  283. *ppDdpAddr = pDdpAddr->ddpao_Next;
  284. // to catch weirdnesses!
  285. pDdpAddr->ddpao_Next = (PDDP_ADDROBJ)0x081294;
  286. break;
  287. }
  288. }
  289. RELEASE_SPIN_LOCK(&pNode->an_Lock, OldIrql);
  290. if (pDdpAddr->ddpao_EventInfo != NULL)
  291. {
  292. AtalkFreeMemory(pDdpAddr->ddpao_EventInfo);
  293. pDdpAddr->ddpao_EventInfo = NULL;
  294. }
  295. // Call the completion routines
  296. if (pDdpAddr->ddpao_CloseComp != NULL)
  297. {
  298. (*pDdpAddr->ddpao_CloseComp)(ATALK_NO_ERROR, pDdpAddr->ddpao_CloseCtx);
  299. pDdpAddr->ddpao_CloseComp = NULL;
  300. }
  301. // Dereference the node for this address
  302. AtalkNodeDereference(pNode);
  303. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  304. ("AtalkDdpPnp..: addr %lx (%lx) put in zombie state\n",
  305. pDdpAddr,pDdpAddr->ddpao_Handler));
  306. }
  307. return ATALK_PENDING;
  308. }
  309. ATALK_ERROR
  310. AtalkDdpInitCloseAddress(
  311. IN PPORT_DESCRIPTOR pPortDesc,
  312. IN PATALK_ADDR pAtalkAddr
  313. )
  314. /*++
  315. Routine Description:
  316. Arguments:
  317. Return Value:
  318. --*/
  319. {
  320. ATALK_ERROR error;
  321. PDDP_ADDROBJ pDdpAddr;
  322. // !!!This should only be called during initialization!!!
  323. KEVENT Event = {0};
  324. // Try to see if the socket exists.
  325. AtalkDdpRefByAddr(pPortDesc, pAtalkAddr, &pDdpAddr, &error);
  326. if (ATALK_SUCCESS(error))
  327. {
  328. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  329. KeInitializeEvent(&Event, NotificationEvent, FALSE);
  330. // Call close with the appropriate completion routine.
  331. error = AtalkDdpCloseAddress(pDdpAddr,
  332. atalkDdpInitCloseComplete,
  333. (PVOID)&Event);
  334. // Remove the reference we added.
  335. AtalkDdpDereference(pDdpAddr);
  336. if (error == ATALK_PENDING)
  337. {
  338. // Wait on event, completion routine will set NdisRequestEvent
  339. KeWaitForSingleObject(&Event,
  340. Executive,
  341. KernelMode,
  342. TRUE,
  343. NULL);
  344. // Assume socket closed successfully.
  345. error = ATALK_NO_ERROR;
  346. }
  347. }
  348. return error;
  349. }
  350. VOID
  351. atalkDdpInitCloseComplete(
  352. ATALK_ERROR Error,
  353. PVOID Ctx
  354. )
  355. /*++
  356. Routine Description:
  357. Arguments:
  358. Return Value:
  359. --*/
  360. {
  361. PKEVENT pEvent = (PKEVENT)Ctx;
  362. if (!ATALK_SUCCESS(Error))
  363. {
  364. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  365. ("atalkDdpInitCloseComplete: Closed with error %lx\n", Error));
  366. }
  367. KeSetEvent(pEvent, 0L, FALSE);
  368. }
  369. ATALK_ERROR
  370. AtalkInitDdpOpenStaticSockets(
  371. IN PPORT_DESCRIPTOR pPortDesc,
  372. IN OUT PATALK_NODE pNode
  373. )
  374. /*++
  375. Routine Description:
  376. Arguments:
  377. Return Value:
  378. --*/
  379. {
  380. PDDP_ADDROBJ pDdpAddr, pDdpAddr1, pDdpAddr2, pDdpAddr3;
  381. ATALK_ERROR error = ATALK_NO_ERROR;
  382. // This is called whenever a new node is created.
  383. do
  384. {
  385. error = AtalkDdpOpenAddress(pPortDesc,
  386. NAMESINFORMATION_SOCKET,
  387. &pNode->an_NodeAddr,
  388. AtalkNbpPacketIn,
  389. NULL,
  390. DDPPROTO_ANY,
  391. NULL,
  392. &pDdpAddr);
  393. if (!ATALK_SUCCESS(error))
  394. break;
  395. // mark the fact that this is an "internal" socket
  396. pDdpAddr->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  397. // A lot of devices today work around the fact that a macintosh uses socket 254
  398. // for lookups from chooser. Agfa is one such beast. To make this work, we reserve
  399. // this socket for Nbp lookups ourselves.
  400. error = AtalkDdpOpenAddress(pPortDesc,
  401. LAST_DYNAMIC_SOCKET,
  402. &pNode->an_NodeAddr,
  403. AtalkNbpPacketIn,
  404. NULL,
  405. DDPPROTO_ANY,
  406. NULL,
  407. &pDdpAddr1);
  408. if (!ATALK_SUCCESS(error))
  409. {
  410. AtalkDdpCloseAddress(pDdpAddr, NULL, NULL);
  411. break;
  412. }
  413. // mark the fact that this is an "internal" socket
  414. pDdpAddr1->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  415. error = AtalkDdpOpenAddress(pPortDesc,
  416. ECHOER_SOCKET,
  417. &pNode->an_NodeAddr,
  418. AtalkAepPacketIn,
  419. NULL,
  420. DDPPROTO_ANY,
  421. NULL,
  422. &pDdpAddr2);
  423. if (!ATALK_SUCCESS(error))
  424. {
  425. AtalkDdpCloseAddress(pDdpAddr, NULL, NULL);
  426. AtalkDdpCloseAddress(pDdpAddr1, NULL, NULL);
  427. break;
  428. }
  429. // mark the fact that this is an "internal" socket
  430. pDdpAddr2->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  431. // NOTE: RTMP uses two protocol types.
  432. error = AtalkDdpOpenAddress(pPortDesc,
  433. RTMP_SOCKET,
  434. &pNode->an_NodeAddr,
  435. AtalkRtmpPacketIn,
  436. NULL,
  437. DDPPROTO_ANY,
  438. NULL,
  439. &pDdpAddr3);
  440. if (!ATALK_SUCCESS(error))
  441. {
  442. AtalkDdpCloseAddress(pDdpAddr, NULL, NULL);
  443. AtalkDdpCloseAddress(pDdpAddr1, NULL, NULL);
  444. AtalkDdpCloseAddress(pDdpAddr2, NULL, NULL);
  445. }
  446. // mark the fact that this is an "internal" socket
  447. pDdpAddr3->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  448. } while (FALSE);
  449. return error;
  450. }
  451. //
  452. // AtalkDdpReceive()
  453. // Called by an external caller to the stack.
  454. // PAMDL is an Appletalk Memory Descriptor List. On NT, it will be an MDL.
  455. //
  456. ATALK_ERROR
  457. AtalkDdpReceive(
  458. IN PDDP_ADDROBJ pDdpAddr,
  459. IN PAMDL pAmdl,
  460. IN USHORT AmdlLen,
  461. IN ULONG RecvFlags,
  462. IN RECEIVE_COMPLETION pRcvCmp,
  463. IN PVOID pRcvCtx OPTIONAL
  464. )
  465. /*++
  466. Routine Description:
  467. Arguments:
  468. Return Value:
  469. --*/
  470. {
  471. ATALK_ERROR error;
  472. PDDP_READ pRead;
  473. NTSTATUS status;
  474. ULONG bytesCopied;
  475. ATALK_ADDR remoteAddr;
  476. KIRQL OldIrql;
  477. BOOLEAN completeRecv = FALSE,
  478. DerefAddr = FALSE;
  479. BOOLEAN pendingDgram = FALSE;
  480. do
  481. {
  482. if (pRcvCmp == NULL)
  483. {
  484. error = ATALK_DDP_INVALID_PARAM;
  485. break;
  486. }
  487. AtalkDdpReferenceByPtr(pDdpAddr, &error);
  488. if (!ATALK_SUCCESS(error))
  489. {
  490. break;
  491. }
  492. DerefAddr = TRUE;
  493. error = ATALK_NO_ERROR;
  494. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  495. if (pDdpAddr->ddpao_Flags & DDPAO_DGRAM_PENDING)
  496. {
  497. if (AmdlLen < pDdpAddr->ddpao_EventInfo->ev_IndDgramLen)
  498. {
  499. error = ATALK_BUFFER_TOO_SMALL;
  500. }
  501. AmdlLen = MIN(AmdlLen, pDdpAddr->ddpao_EventInfo->ev_IndDgramLen);
  502. status = TdiCopyBufferToMdl(
  503. pDdpAddr->ddpao_EventInfo->ev_IndDgram,
  504. 0,
  505. AmdlLen,
  506. pAmdl,
  507. 0,
  508. &bytesCopied);
  509. remoteAddr = pDdpAddr->ddpao_EventInfo->ev_IndSrc;
  510. pDdpAddr->ddpao_Flags &= ~DDPAO_DGRAM_PENDING;
  511. completeRecv = TRUE;
  512. }
  513. else
  514. {
  515. // This case never really will be executed for non-blocking sockets.
  516. // Dont bother about this alloc with spinlock held for now.
  517. // RACE CONDITION is with a packet coming in and setting DGRAM_PENDING.
  518. if ((pRead = AtalkAllocMemory(sizeof(DDP_READ))) == NULL)
  519. {
  520. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  521. error = ATALK_RESR_MEM;
  522. break;
  523. }
  524. InsertTailList(&pDdpAddr->ddpao_ReadLinkage, &pRead->dr_Linkage);
  525. DerefAddr = FALSE;
  526. pRead->dr_OpBuf = pAmdl;
  527. pRead->dr_OpBufLen = AmdlLen;
  528. pRead->dr_RcvCmp = pRcvCmp;
  529. pRead->dr_RcvCtx = pRcvCtx;
  530. error = ATALK_PENDING;
  531. }
  532. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  533. } while (FALSE);
  534. if (completeRecv)
  535. {
  536. ASSERT((error == ATALK_NO_ERROR) || (error == ATALK_BUFFER_TOO_SMALL));
  537. (*pRcvCmp)(error,
  538. pAmdl,
  539. AmdlLen,
  540. &remoteAddr,
  541. pRcvCtx);
  542. // And return pending for sure!
  543. error = ATALK_PENDING;
  544. DerefAddr = TRUE;
  545. }
  546. if (DerefAddr)
  547. {
  548. AtalkDdpDereference(pDdpAddr);
  549. }
  550. return error;
  551. }
  552. //
  553. // DdpSend()
  554. // This function is used to deliver packets submitted by the ddp clients.
  555. // The packets are assummed to either be destined for one of the nodes on
  556. // the port, or need to be routed to another port (if router is on), or to
  557. // be transmitted onto the physical medium.
  558. //
  559. // This takes a buffer descriptor as an input. This can contain either a
  560. // PAMDL or a PBYTE depending on where the data is coming from (user space
  561. // or router code respectively). In addition, it will take an optional header
  562. // buffer that will be appended to the ddp header. The buffer descriptor is
  563. // optional, that if NULL, it will be construed as a zero-length send.
  564. //
  565. ATALK_ERROR
  566. AtalkDdpSend(
  567. IN PDDP_ADDROBJ pDdpAddr,
  568. IN PATALK_ADDR pDestAddr,
  569. IN BYTE Protocol,
  570. IN BOOLEAN DefinitelyRemoteAddr,
  571. IN PBUFFER_DESC pBuffDesc OPTIONAL,
  572. IN PBYTE pOptHdr OPTIONAL,
  573. IN USHORT OptHdrLen OPTIONAL,
  574. IN PBYTE pMcastAddr OPTIONAL,
  575. IN PSEND_COMPL_INFO pSendInfo OPTIONAL
  576. )
  577. /*++
  578. Routine Description:
  579. Arguments:
  580. Return Value:
  581. --*/
  582. {
  583. ATALK_ERROR error;
  584. BOOLEAN shouldBeRouted;
  585. PPORT_DESCRIPTOR pPortDesc;
  586. ATALK_ADDR srcAddr;
  587. KIRQL OldIrql;
  588. BOOLEAN delivered = FALSE;
  589. // NULL buffer descriptor => 0-length send.
  590. ASSERT((pBuffDesc == NULL) || (pBuffDesc->bd_Length > 0));
  591. #ifdef DDP_STRICT
  592. // Check destination address
  593. if (INVALID_ADDRESS(pDestAddr))
  594. {
  595. return ATALK_DDP_INVALID_ADDR;
  596. }
  597. // Check the datagram length.
  598. if (pBuffDesc)
  599. {
  600. USHORT dgramLen;
  601. AtalkSizeOfBuffDescData(pBuffDesc, &dgramLen);
  602. if (dgramLen > MAX_DGRAM_SIZE)
  603. {
  604. return ATALK_BUFFER_TOO_BIG;
  605. }
  606. }
  607. #endif
  608. //
  609. // if this socket is in a zombie state (pnp changes are over) then reject
  610. // this send
  611. //
  612. if (pDdpAddr->ddpao_Flags & DDPAO_SOCK_PNPZOMBIE)
  613. {
  614. return ATALK_DDP_INVALID_ADDR;
  615. }
  616. // Get a pointer to the port on which the socket exists.
  617. pPortDesc = pDdpAddr->ddpao_Node->an_Port;
  618. // Get the source address
  619. srcAddr = pDdpAddr->ddpao_Addr;
  620. if (!DefinitelyRemoteAddr)
  621. {
  622. // All socket handlers assume that they are called at DISPACTH. Make it so.
  623. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  624. AtalkDdpOutBufToNodesOnPort(pPortDesc,
  625. &srcAddr,
  626. pDestAddr,
  627. Protocol,
  628. pBuffDesc,
  629. pOptHdr,
  630. OptHdrLen,
  631. &delivered);
  632. KeLowerIrql(OldIrql);
  633. if (delivered)
  634. {
  635. // Ok, packet meant for one of our own nodes on this port,
  636. // and we delivered it. Call the completion routine.
  637. if (pSendInfo != NULL)
  638. {
  639. (*pSendInfo->sc_TransmitCompletion)(NDIS_STATUS_SUCCESS, pSendInfo);
  640. }
  641. return ATALK_PENDING;
  642. }
  643. }
  644. ASSERT (!delivered);
  645. // Can our router handle it?
  646. shouldBeRouted = ((pPortDesc->pd_Flags & PD_ROUTER_RUNNING) &&
  647. (pDestAddr->ata_Network != CABLEWIDE_BROADCAST_NETWORK) &&
  648. !(WITHIN_NETWORK_RANGE(pDestAddr->ata_Network,
  649. &pPortDesc->pd_NetworkRange)) &&
  650. !(WITHIN_NETWORK_RANGE(pDestAddr->ata_Network,
  651. &AtalkStartupNetworkRange)));
  652. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  653. ("AtalkDdpSend: destNet %lx shouldBeRouted %s\n",
  654. pDestAddr->ata_Network, shouldBeRouted ? "Yes" : "No"));
  655. if (shouldBeRouted)
  656. {
  657. ASSERT (!((WITHIN_NETWORK_RANGE(pDestAddr->ata_Network, &pPortDesc->pd_NetworkRange)) &&
  658. (pDestAddr->ata_Node == ATALK_BROADCAST_NODE)));
  659. // If we're a router and the packet isn't destined for the target ports
  660. // local network, let our router handle it -- rather than sending to
  661. // whatever the "best router" is or to "a router".
  662. do
  663. {
  664. // This algorithm is taken from the "Appletalk Phase 2 Specification".
  665. // If the destination network number is within the range of the reception
  666. // port's network range and the destination node number is broadcast, then
  667. // we can drop the packet on the floor -- it is a network specific broadcast
  668. // not for this router. Note that we've already delivered the packet, and
  669. // thus not gotten here, if it was really addressed to the network of any
  670. // node owned by the reception port (in AtalkDdpPacketIn).
  671. // Also:
  672. // Try to find an entry in the routing table that contains the target
  673. // network. If not found, discard the packet.
  674. PDDP_ADDROBJ pRouteDdpAddr;
  675. PRTE pRte;
  676. PPORT_DESCRIPTOR pDestPortDesc;
  677. PATALK_NODE pRouterNode;
  678. ATALK_ADDR actualDest;
  679. if ((pRte = AtalkRtmpReferenceRte(pDestAddr->ata_Network)) == NULL)
  680. {
  681. DBGPRINT(DBG_COMP_ROUTER, DBG_LEVEL_FATAL,
  682. ("AtalkDdpRouter: %lx RtmpRte/Not in ThisCableRange\n",
  683. pDestAddr->ata_Network));
  684. error = ATALK_RESR_MEM;
  685. break;
  686. }
  687. do
  688. {
  689. // Get the port descriptor corres. to the RTE
  690. pDestPortDesc = pRte->rte_PortDesc;
  691. ASSERT(VALID_PORT(pDestPortDesc));
  692. // If the target network's hop count is non-zero, we really need to send
  693. // the beast, so, just do it!
  694. if (pRte->rte_NumHops != 0)
  695. {
  696. // Too many hops?
  697. error = AtalkDdpTransmit(pDestPortDesc,
  698. &srcAddr,
  699. pDestAddr,
  700. Protocol,
  701. pBuffDesc,
  702. pOptHdr,
  703. OptHdrLen,
  704. 1, // HopCount
  705. NULL, // pZoneMcastAddr
  706. &pRte->rte_NextRouter,
  707. pSendInfo);
  708. break;
  709. }
  710. // If the destination node is zero, the packet is really destined for the
  711. // router's node on this port.
  712. if (pDestAddr->ata_Node == ANY_ROUTER_NODE)
  713. {
  714. // Try to reference this port, if not successful, its probably
  715. // closing down. Grab the port lock and read the router node address.
  716. // No need to reference, just ensure its not null.
  717. ACQUIRE_SPIN_LOCK(&pDestPortDesc->pd_Lock, &OldIrql);
  718. if ((pDestPortDesc->pd_Flags & PD_CLOSING) == 0)
  719. {
  720. ASSERT(pDestPortDesc->pd_RefCount > 0);
  721. pDestPortDesc->pd_RefCount++;
  722. }
  723. else
  724. {
  725. ASSERTMSG("AtalkDdpRouter: Could not ref port!\n", 0);
  726. error = ATALK_PORT_CLOSING;
  727. RELEASE_SPIN_LOCK(&pDestPortDesc->pd_Lock, OldIrql);
  728. break;
  729. }
  730. pRouterNode = pDestPortDesc->pd_RouterNode;
  731. if (pRouterNode != NULL)
  732. {
  733. actualDest.ata_Network = pRouterNode->an_NodeAddr.atn_Network;
  734. actualDest.ata_Node = pRouterNode->an_NodeAddr.atn_Node;
  735. // Set the actual destination socket.
  736. actualDest.ata_Socket = pDestAddr->ata_Socket;
  737. }
  738. else
  739. {
  740. ASSERTMSG("AtalkDdpRouter: pRouter node is null!\n", 0);
  741. error = ATALK_DDP_NOTFOUND;
  742. }
  743. if (ATALK_SUCCESS(error))
  744. {
  745. AtalkDdpRefByAddrNode(pDestPortDesc,
  746. &actualDest,
  747. pRouterNode,
  748. &pRouteDdpAddr,
  749. &error);
  750. }
  751. RELEASE_SPIN_LOCK(&pDestPortDesc->pd_Lock, OldIrql);
  752. if (ATALK_SUCCESS(error))
  753. {
  754. KIRQL OldIrql;
  755. // Socket handlers assume that they are called at DISPATCH. Make it so.
  756. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  757. AtalkDdpInvokeHandlerBufDesc(pDestPortDesc,
  758. pRouteDdpAddr,
  759. &srcAddr,
  760. pDestAddr, // Pass in the actual destination
  761. Protocol,
  762. pBuffDesc,
  763. pOptHdr,
  764. OptHdrLen);
  765. // Remove the reference on the socket
  766. AtalkDdpDereferenceDpc(pRouteDdpAddr);
  767. KeLowerIrql(OldIrql);
  768. }
  769. else
  770. {
  771. ASSERTMSG("AtalkDdpRouter: pSocket on router node is null!\n", 0);
  772. }
  773. break;
  774. }
  775. // Okay, now walk through the nodes on the target port, looking for a
  776. // home for this packet.
  777. if (!DefinitelyRemoteAddr)
  778. {
  779. // All socket handlers assume that they are called at DISPACTH. Make it so.
  780. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  781. AtalkDdpOutBufToNodesOnPort(pDestPortDesc,
  782. &srcAddr,
  783. pDestAddr,
  784. Protocol,
  785. pBuffDesc,
  786. pOptHdr,
  787. OptHdrLen,
  788. &delivered);
  789. KeLowerIrql(OldIrql);
  790. if (delivered)
  791. {
  792. if (pSendInfo != NULL)
  793. {
  794. (*pSendInfo->sc_TransmitCompletion)(NDIS_STATUS_SUCCESS, pSendInfo);
  795. }
  796. error = ATALK_NO_ERROR;
  797. break;
  798. }
  799. }
  800. // We need to deliver this packet to a local ports network.
  801. error = AtalkDdpTransmit(pDestPortDesc,
  802. &srcAddr,
  803. pDestAddr,
  804. Protocol,
  805. pBuffDesc,
  806. pOptHdr,
  807. OptHdrLen,
  808. 1, // HopCount
  809. NULL, // pZoneMcastAddr,
  810. NULL,
  811. pSendInfo);
  812. } while (FALSE);
  813. INTERLOCKED_INCREMENT_LONG_DPC(
  814. &pDestPortDesc->pd_PortStats.prtst_NumPktRoutedOut,
  815. &AtalkStatsLock.SpinLock);
  816. AtalkRtmpDereferenceRte(pRte, FALSE); // Lock held?
  817. } while (FALSE);
  818. INTERLOCKED_INCREMENT_LONG_DPC(
  819. &pPortDesc->pd_PortStats.prtst_NumPktRoutedIn,
  820. &AtalkStatsLock.SpinLock);
  821. }
  822. else
  823. {
  824. error = AtalkDdpTransmit(pPortDesc,
  825. &srcAddr,
  826. pDestAddr,
  827. Protocol,
  828. pBuffDesc,
  829. pOptHdr,
  830. OptHdrLen,
  831. 0, // HopCnt,
  832. pMcastAddr,
  833. NULL, // pXmitDestNode,
  834. pSendInfo);
  835. }
  836. return error;
  837. }
  838. //
  839. // DdpTransmit()
  840. // This function is called to build the headers for the packet and send it
  841. // out via the depend level functions. It is assumed at this point that the
  842. // packet is destined for nodes not currently controlled by this stack.
  843. //
  844. // KnownMulticastAddress: Although the DDP destination is encoded using
  845. // 'Destination', if this parameter is non-null, the packet is actually
  846. // sent to this address.
  847. //
  848. // TransmitDestination: Again, as above, the router uses this to pass on the
  849. // packet to the next router it needs to go to, if 'Destination' is still one
  850. // or more hops away.
  851. //
  852. // This is only called from within ddp send or by the router code (rtmp/zip/router).
  853. //
  854. ATALK_ERROR
  855. AtalkDdpTransmit(
  856. IN PPORT_DESCRIPTOR pPortDesc,
  857. IN PATALK_ADDR pSrcAddr,
  858. IN PATALK_ADDR pDestAddr,
  859. IN BYTE Protocol,
  860. IN PBUFFER_DESC pBuffDesc OPTIONAL,
  861. IN PBYTE pOptHdr OPTIONAL,
  862. IN USHORT OptHdrLen OPTIONAL,
  863. IN USHORT HopCnt,
  864. IN PBYTE pMcastAddr OPTIONAL,
  865. IN PATALK_NODEADDR pXmitDestNode OPTIONAL,
  866. IN PSEND_COMPL_INFO pSendInfo OPTIONAL
  867. )
  868. /*++
  869. Routine Description:
  870. Arguments:
  871. Return Value:
  872. --*/
  873. {
  874. PBYTE pDgram, pDgramStart, pLinkDdpOptHdr;
  875. PBUFFER_DESC pPktDesc;
  876. USHORT linkLen;
  877. ATALK_NODEADDR srcNode;
  878. ATALK_NODEADDR destNode;
  879. USHORT actualLength;
  880. ATALK_NODEADDR actualDest;
  881. PBUFFER_DESC probe;
  882. PBRE routerNode;
  883. USHORT bufLen = 0;
  884. USHORT checksum = 0;
  885. PBYTE knownAddress = NULL;
  886. PBYTE knownRouteInfo = NULL;
  887. USHORT knownRouteInfoLen = 0;
  888. BOOLEAN broadcast = FALSE;
  889. ATALK_ERROR error = ATALK_NO_ERROR;
  890. BOOLEAN shortDdpHeader = FALSE;
  891. BOOLEAN errorFreePkt = FALSE;
  892. PARAPCONN pArapConn = NULL;
  893. PATCPCONN pAtcpConn = NULL;
  894. DWORD StatusCode;
  895. DWORD dwFlags;
  896. USHORT SrpLen;
  897. PBYTE pTmpPtr;
  898. NDIS_STATUS status;
  899. BOOLEAN fThisIsPPP;
  900. PVOID pRasConn;
  901. //
  902. // The basic transmit algorithum is:
  903. //
  904. // if (non-extended-network)
  905. // {
  906. // if ((destination-network is 0 or
  907. // destination-network is NetworkRange.firstNetwork) and
  908. // (source-network is 0 or
  909. // source-network is NetworkRange.firstNetwork))
  910. // {
  911. // <send short form DDP packet to local network>
  912. // return-okay
  913. // }
  914. // }
  915. // if (destination-network is CableWideBroadcastNetworkNumber or
  916. // destination-network in NetworkRange or
  917. // destination-network in SartupRange or
  918. // {
  919. // <send long form DDP packet to local network>
  920. // return-okay
  921. // }
  922. // if (destination-network-and-node in best-router-cache)
  923. // {
  924. // <send long form DDP packet to best router>
  925. // return-okay
  926. // }
  927. // if (seen-a-router-recently)
  928. // {
  929. // <send long form DDP packet to a-router>
  930. // return-okay
  931. // }
  932. // return-error
  933. destNode.atn_Network = pDestAddr->ata_Network;
  934. destNode.atn_Node = pDestAddr->ata_Node;
  935. actualDest.atn_Network = UNKNOWN_NETWORK;
  936. actualDest.atn_Node = UNKNOWN_NODE;
  937. do
  938. {
  939. if (pBuffDesc != NULL)
  940. {
  941. // Get the buffer length. Check the datagram length.
  942. AtalkSizeOfBuffDescData(pBuffDesc, &bufLen);
  943. ASSERT(bufLen > 0);
  944. }
  945. #ifdef DDP_STRICT
  946. // Check destination address
  947. if (INVALID_ADDRESS(pDestAddr) || INVALID_ADDRESS(pSrcAddr))
  948. {
  949. error = ATALK_DDP_INVALID_ADDR;
  950. break;
  951. }
  952. if (pBuffDesc != NULL)
  953. {
  954. // Ensure we do not have a chained datagram.
  955. if (pBuffDesc->bd_Next != NULL)
  956. {
  957. KeBugCheck(0);
  958. }
  959. if (bufLen > MAX_DGRAM_SIZE)
  960. {
  961. error = ATALK_BUFFER_TOO_BIG;
  962. break;
  963. }
  964. }
  965. if (OptHdrLen > MAX_OPTHDR_LEN)
  966. {
  967. error = ATALK_BUFFER_TOO_BIG;
  968. break;
  969. }
  970. #endif
  971. //
  972. // is the desination one of our dial-in clients?
  973. //
  974. pRasConn = FindAndRefRasConnByAddr(destNode, &dwFlags, &fThisIsPPP);
  975. if ((pRasConn == NULL) && (pPortDesc->pd_Flags & PD_RAS_PORT))
  976. {
  977. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  978. ("AtalkDdpTransmit: pArapConn is NULL! Network, Node = %lx %lx\n",
  979. pDestAddr->ata_Network,pDestAddr->ata_Node));
  980. error = ATALK_FAILURE;
  981. break;
  982. }
  983. pArapConn = NULL;
  984. pAtcpConn = NULL;
  985. // if this is a dial-in client, see if it's PPP or ARAP
  986. if (pRasConn)
  987. {
  988. if (fThisIsPPP)
  989. {
  990. pAtcpConn = (PATCPCONN)pRasConn;
  991. // we can send only if the PPP connection is up
  992. if (!(dwFlags & ATCP_CONNECTION_UP))
  993. {
  994. DerefPPPConn(pAtcpConn);
  995. pAtcpConn = NULL;
  996. }
  997. }
  998. else
  999. {
  1000. pArapConn = (PARAPCONN)pRasConn;
  1001. }
  1002. }
  1003. //
  1004. // if the destination is a dial-in client, we have more work to do
  1005. //
  1006. // PPP client?
  1007. if (pAtcpConn != NULL)
  1008. {
  1009. // the buffer that will hold both the link and ddp hdrs.
  1010. shortDdpHeader = FALSE;
  1011. AtalkNdisAllocBuf(&pPktDesc);
  1012. if (pPktDesc == NULL)
  1013. {
  1014. error = ATALK_FAILURE;
  1015. break;
  1016. }
  1017. // In cases of error, free the allocated packet.
  1018. errorFreePkt = TRUE;
  1019. actualLength = bufLen + LDDP_HDR_LEN + OptHdrLen;
  1020. pLinkDdpOptHdr = pPktDesc->bd_CharBuffer;
  1021. AtalkNdisBuildPPPPHdr(pLinkDdpOptHdr, pAtcpConn);
  1022. linkLen = WAN_LINKHDR_LEN;
  1023. break;
  1024. }
  1025. // nope, ARAP client?
  1026. else if ( pArapConn != NULL )
  1027. {
  1028. shortDdpHeader = FALSE; // ARAP mandates always long form
  1029. AtalkNdisAllocBuf(&pPktDesc);
  1030. if (pPktDesc == NULL)
  1031. {
  1032. error = ATALK_FAILURE;
  1033. break;
  1034. }
  1035. // In cases of error, free the allocated packet.
  1036. errorFreePkt = TRUE;
  1037. actualLength = bufLen + LDDP_HDR_LEN + OptHdrLen;
  1038. pLinkDdpOptHdr = pTmpPtr = pPktDesc->bd_CharBuffer;
  1039. linkLen = ARAP_LAP_HDRSIZE + ARAP_HDRSIZE;
  1040. // don't count the 2 length bytes
  1041. SrpLen = actualLength + linkLen - sizeof(USHORT);
  1042. //
  1043. // put the 2 SRP bytes and the 1 byte DGroup flag (we have enough room)
  1044. //
  1045. PUTSHORT2SHORT(pTmpPtr, SrpLen);
  1046. pTmpPtr += sizeof(USHORT);
  1047. // the Dgroup byte
  1048. *pTmpPtr++ = (ARAP_SFLAG_PKT_DATA | ARAP_SFLAG_LAST_GROUP);
  1049. // the LAP hdr
  1050. *pTmpPtr++ = 0;
  1051. *pTmpPtr++ = 0;
  1052. *pTmpPtr++ = 2;
  1053. break;
  1054. }
  1055. // For non-extended networks, we may want to send a short DDP header.
  1056. if (!(EXT_NET(pPortDesc)) &&
  1057. ((pDestAddr->ata_Network == UNKNOWN_NETWORK) ||
  1058. (pDestAddr->ata_Network == pPortDesc->pd_NetworkRange.anr_FirstNetwork)) &&
  1059. ((pSrcAddr->ata_Network == UNKNOWN_NETWORK) ||
  1060. (pSrcAddr->ata_Network == pPortDesc->pd_NetworkRange.anr_FirstNetwork)))
  1061. {
  1062. // Use a short ddp header. Call the port handler to first alloc
  1063. // the buffer that will hold both the link and ddp hdrs.
  1064. shortDdpHeader = TRUE;
  1065. AtalkNdisAllocBuf(&pPktDesc);
  1066. if (pPktDesc == NULL)
  1067. {
  1068. error = ATALK_FAILURE;
  1069. break;
  1070. }
  1071. // In cases of error, free the allocated packet.
  1072. errorFreePkt = TRUE;
  1073. // pPkt will be the beginning of the packet and pDgram is where
  1074. // we fill in the ddp header.
  1075. actualLength = bufLen + SDDP_HDR_LEN + OptHdrLen;
  1076. pLinkDdpOptHdr = pPktDesc->bd_CharBuffer;
  1077. linkLen = 0;
  1078. ASSERT (pPortDesc->pd_NdisPortType == NdisMediumLocalTalk);
  1079. // Build the LAP header. This will build it from pDgram backwards,
  1080. // and set the pPkt pointer as the packet to be freed in the
  1081. // built buffer descriptor.
  1082. linkLen = AtalkNdisBuildLTHdr(pLinkDdpOptHdr,
  1083. &pDestAddr->ata_Node,
  1084. pSrcAddr->ata_Node,
  1085. ALAP_SDDP_HDR_TYPE);
  1086. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  1087. ("AtalkDdpTransmit: Sending short hdr on non-ext net! %ld\n",
  1088. pDestAddr->ata_Node, pDestAddr->ata_Network));
  1089. break;
  1090. }
  1091. // LONG DDP HEADER
  1092. // Compute the extended AppleTalk node number that we'll really need to
  1093. // send the packet to.
  1094. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  1095. ("AtalkDdpTransmit: Building a long ddp header for bufdesc %lx on port %lx\n",
  1096. pBuffDesc, pPortDesc));
  1097. do
  1098. {
  1099. if (pMcastAddr != NULL)
  1100. {
  1101. knownAddress = pMcastAddr ;
  1102. break;
  1103. }
  1104. if (pXmitDestNode != NULL)
  1105. {
  1106. actualDest = *pXmitDestNode;
  1107. break;
  1108. }
  1109. if ((WITHIN_NETWORK_RANGE(pDestAddr->ata_Network,
  1110. &pPortDesc->pd_NetworkRange)) ||
  1111. (pDestAddr->ata_Network == CABLEWIDE_BROADCAST_NETWORK) ||
  1112. (WITHIN_NETWORK_RANGE(pDestAddr->ata_Network,
  1113. &AtalkStartupNetworkRange)))
  1114. {
  1115. actualDest.atn_Node = pDestAddr->ata_Node;
  1116. actualDest.atn_Network = pDestAddr->ata_Network;
  1117. broadcast = (pDestAddr->ata_Node == ATALK_BROADCAST_NODE);
  1118. break;
  1119. }
  1120. atalkDdpFindInBrc(pPortDesc, destNode.atn_Network, &routerNode);
  1121. if (routerNode != NULL)
  1122. {
  1123. // Okay, we know where to go.
  1124. knownAddress = routerNode->bre_RouterAddr;
  1125. knownRouteInfo = (PBYTE)routerNode + sizeof(BRE);
  1126. knownRouteInfoLen = routerNode->bre_RouteInfoLen;
  1127. break;
  1128. }
  1129. if (pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  1130. {
  1131. actualDest = pPortDesc->pd_ARouter;
  1132. break;
  1133. }
  1134. // No router known. What do we do ? If its not an extended net,
  1135. // just send it - else return error.
  1136. if (EXT_NET(pPortDesc))
  1137. {
  1138. error = ATALK_DDP_NO_ROUTER;
  1139. break;
  1140. }
  1141. actualDest.atn_Node = pDestAddr->ata_Node;
  1142. actualDest.atn_Network = pDestAddr->ata_Network;
  1143. broadcast = (pDestAddr->ata_Node == ATALK_BROADCAST_NODE);
  1144. } while (FALSE);
  1145. if (error != ATALK_NO_ERROR)
  1146. {
  1147. break;
  1148. }
  1149. AtalkNdisAllocBuf(&pPktDesc);
  1150. if (pPktDesc == NULL)
  1151. {
  1152. error = ATALK_FAILURE;
  1153. break;
  1154. }
  1155. // In cases of error, free the allocated packet.
  1156. errorFreePkt = TRUE;
  1157. pLinkDdpOptHdr = pPktDesc->bd_CharBuffer;
  1158. linkLen = 0;
  1159. actualLength = bufLen + LDDP_HDR_LEN + OptHdrLen;
  1160. // If we already know where we're headed, just blast it out. Also,
  1161. // if we're broadcasting, just do it. "knownAddress" will be NULL
  1162. // if we're broadcasting and that will cause the BuildHeader to make
  1163. // a broadcast packet.
  1164. if (EXT_NET(pPortDesc) &&
  1165. ((knownAddress != NULL) ||
  1166. broadcast ||
  1167. (actualDest.atn_Network == CABLEWIDE_BROADCAST_NETWORK)))
  1168. {
  1169. // Build the LAP header.
  1170. AtalkNdisBuildHdr(pPortDesc,
  1171. pLinkDdpOptHdr,
  1172. linkLen,
  1173. actualLength,
  1174. knownAddress,
  1175. knownRouteInfo,
  1176. knownRouteInfoLen,
  1177. APPLETALK_PROTOCOL);
  1178. break;
  1179. }
  1180. // On non-extended networks, just send the packet to the desired node --
  1181. // no AARP games here.
  1182. if (!EXT_NET(pPortDesc))
  1183. {
  1184. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  1185. ("AtalkDdpTransmit: Sending long hdr on non-ext net! %ld\n",
  1186. actualDest.atn_Network, actualDest.atn_Node));
  1187. ASSERT (pPortDesc->pd_NdisPortType == NdisMediumLocalTalk);
  1188. linkLen = AtalkNdisBuildLTHdr(pLinkDdpOptHdr,
  1189. &actualDest.atn_Node,
  1190. pSrcAddr->ata_Node,
  1191. ALAP_LDDP_HDR_TYPE);
  1192. break;
  1193. }
  1194. // We're sending to a particular node on an extended network.
  1195. // Do we know its hardware address ? If so, send it out.
  1196. {
  1197. KIRQL OldIrql;
  1198. USHORT index;
  1199. PAMT pAmt;
  1200. // Go through the AMT and find the entry for the destination
  1201. // address if present.
  1202. index = HASH_ATALK_NODE(&actualDest) % PORT_AMT_HASH_SIZE;
  1203. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1204. for (pAmt = pPortDesc->pd_Amt[index];
  1205. pAmt != NULL;
  1206. pAmt = pAmt->amt_Next)
  1207. {
  1208. if (ATALK_NODES_EQUAL(&pAmt->amt_Target, &actualDest))
  1209. {
  1210. ASSERT(EXT_NET(pPortDesc));
  1211. AtalkNdisBuildHdr(pPortDesc,
  1212. pLinkDdpOptHdr,
  1213. linkLen,
  1214. actualLength,
  1215. pAmt->amt_HardwareAddr,
  1216. (PBYTE)pAmt+sizeof(AMT),
  1217. pAmt->amt_RouteInfoLen,
  1218. APPLETALK_PROTOCOL);
  1219. error = ATALK_NO_ERROR;
  1220. break;
  1221. }
  1222. }
  1223. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1224. if (pAmt == NULL)
  1225. {
  1226. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_WARN,
  1227. ("atalkDdpFindInAmt: Could not find %lx.%lx\n",
  1228. actualDest.atn_Network, actualDest.atn_Node));
  1229. error = ATALK_DDP_NO_AMT_ENTRY;
  1230. }
  1231. else break; // Found the actual h/w address we want to go to.
  1232. }
  1233. // Free up the allocated header buffer.
  1234. errorFreePkt = TRUE;
  1235. ASSERT(!ATALK_SUCCESS(error));
  1236. // We dont have the hardware address for the logical address that we
  1237. // need to send the packet to. Send out aarp requests and drop this packet.
  1238. // The higher layers can retry later if they have to.
  1239. srcNode.atn_Network = pSrcAddr->ata_Network;
  1240. srcNode.atn_Node = pSrcAddr->ata_Node;
  1241. probe = BUILD_AARPREQUEST(pPortDesc,
  1242. MAX_HW_ADDR_LEN,
  1243. srcNode,
  1244. actualDest);
  1245. if (probe != NULL)
  1246. {
  1247. #ifdef PROFILING
  1248. INTERLOCKED_INCREMENT_LONG(
  1249. &pPortDesc->pd_PortStats.prtst_NumAarpProbesOut,
  1250. &AtalkStatsLock.SpinLock);
  1251. #endif
  1252. // Send the aarp packet.
  1253. error = AtalkNdisSendPacket(pPortDesc,
  1254. probe,
  1255. AtalkAarpSendComplete,
  1256. NULL);
  1257. if (!ATALK_SUCCESS(error))
  1258. {
  1259. TMPLOGERR()
  1260. AtalkAarpSendComplete(NDIS_STATUS_FAILURE,
  1261. probe,
  1262. NULL);
  1263. }
  1264. }
  1265. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_WARN,
  1266. ("AMT Entry not found for %lx.%lx\n",
  1267. pDestAddr->ata_Network, pDestAddr->ata_Node));
  1268. error = ATALK_DDP_NO_AMT_ENTRY;
  1269. break;
  1270. } while (FALSE);
  1271. // Do we need to send the packet?
  1272. if (ATALK_SUCCESS(error))
  1273. {
  1274. ASSERT(HopCnt <= RTMP_MAX_HOPS);
  1275. // Remember the beginning of the dgram
  1276. pDgramStart = pDgram = pLinkDdpOptHdr + linkLen;
  1277. if (!shortDdpHeader)
  1278. {
  1279. *pDgram++ = (DDP_HOP_COUNT(HopCnt) + DDP_MSB_LEN(actualLength));
  1280. PUTSHORT2BYTE(pDgram, actualLength);
  1281. pDgram++;
  1282. ASSERT(checksum == 0);
  1283. PUTSHORT2SHORT(pDgram, checksum);
  1284. pDgram += sizeof(USHORT);
  1285. PUTSHORT2SHORT(pDgram, pDestAddr->ata_Network);
  1286. pDgram += sizeof(USHORT);
  1287. PUTSHORT2SHORT(pDgram, pSrcAddr->ata_Network);
  1288. pDgram += sizeof(USHORT);
  1289. *pDgram++ = pDestAddr->ata_Node;
  1290. *pDgram++ = pSrcAddr->ata_Node;
  1291. *pDgram++ = pDestAddr->ata_Socket;
  1292. *pDgram++ = pSrcAddr->ata_Socket;
  1293. *pDgram++ = Protocol;
  1294. // Copy the optional header if present
  1295. if (OptHdrLen > 0)
  1296. {
  1297. ASSERT(pOptHdr != NULL);
  1298. RtlCopyMemory(pDgram, pOptHdr, OptHdrLen);
  1299. }
  1300. // Set length in the buffer descriptor.
  1301. AtalkSetSizeOfBuffDescData(pPktDesc,
  1302. linkLen + LDDP_HDR_LEN + OptHdrLen);
  1303. }
  1304. else
  1305. {
  1306. *pDgram++ = DDP_MSB_LEN(actualLength);
  1307. PUTSHORT2BYTE(pDgram, actualLength);
  1308. pDgram++;
  1309. *pDgram++ = pDestAddr->ata_Socket;
  1310. *pDgram++ = pSrcAddr->ata_Socket;
  1311. *pDgram++ = Protocol;
  1312. // Copy the optional header if present
  1313. if (OptHdrLen > 0)
  1314. {
  1315. ASSERT(pOptHdr != NULL);
  1316. RtlCopyMemory(pDgram, pOptHdr, OptHdrLen);
  1317. }
  1318. // Set length in the buffer descriptor.
  1319. AtalkSetSizeOfBuffDescData(pPktDesc,
  1320. linkLen + SDDP_HDR_LEN + OptHdrLen);
  1321. }
  1322. // Chain the passed in buffer desc onto the tail of the one
  1323. // returned above.
  1324. AtalkPrependBuffDesc(pPktDesc, pBuffDesc);
  1325. // Okay, set checksum if needed.
  1326. if (pPortDesc->pd_Flags & PD_SEND_CHECKSUMS)
  1327. {
  1328. // Temporary skip over the leading unchecksumed bytes.
  1329. checksum = AtalkDdpCheckSumBufferDesc(pPktDesc,
  1330. (USHORT)(linkLen + LEADING_UNCHECKSUMED_BYTES));
  1331. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  1332. ("AtalkDdpTransmit: checksum %lx\n", checksum));
  1333. PUTSHORT2SHORT(&pDgramStart[LDDP_CHECKSUM_OFFSET], checksum);
  1334. }
  1335. INTERLOCKED_ADD_STATISTICS(&pPortDesc->pd_PortStats.prtst_DataOut,
  1336. AtalkSizeBuffDesc(pPktDesc),
  1337. &AtalkStatsLock.SpinLock);
  1338. //
  1339. // is this packet going to an Arap client? If so, we may need to compress,
  1340. // and do other processing
  1341. //
  1342. if (pArapConn)
  1343. {
  1344. StatusCode = ArapSendPrepare( pArapConn,
  1345. pPktDesc,
  1346. ARAP_SEND_PRIORITY_HIGH );
  1347. if (StatusCode == ARAPERR_NO_ERROR)
  1348. {
  1349. // Send the packet(s)
  1350. ArapNdisSend(pArapConn, &pArapConn->HighPriSendQ);
  1351. status = NDIS_STATUS_SUCCESS;
  1352. }
  1353. else
  1354. {
  1355. status = NDIS_STATUS_FAILURE;
  1356. }
  1357. AtalkDdpSendComplete(status, pPktDesc, pSendInfo);
  1358. // Return pending here
  1359. error = ATALK_PENDING;
  1360. }
  1361. else
  1362. {
  1363. // PPP packets need to go over the RAS port
  1364. if (pAtcpConn)
  1365. {
  1366. pPortDesc = RasPortDesc;
  1367. }
  1368. // Send the packet. The completion routine will handle freeing
  1369. // the buffer chain.
  1370. error = AtalkNdisSendPacket(pPortDesc,
  1371. pPktDesc,
  1372. AtalkDdpSendComplete,
  1373. pSendInfo);
  1374. if (!ATALK_SUCCESS(error))
  1375. {
  1376. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1377. ("AtalkDdpTransmit: AtalkNdisSendPacket failed %ld\n",error));
  1378. AtalkDdpSendComplete(NDIS_STATUS_FAILURE,
  1379. pPktDesc,
  1380. pSendInfo);
  1381. // Return pending. We've alredy called the completion
  1382. // routine here, which will have called the callers
  1383. // completion routine.
  1384. error = ATALK_PENDING;
  1385. }
  1386. }
  1387. }
  1388. // Ras connection? remove the refcount put by FindAndRefRasConnByAddr
  1389. if (pAtcpConn)
  1390. {
  1391. DerefPPPConn(pAtcpConn);
  1392. }
  1393. else if (pArapConn)
  1394. {
  1395. DerefArapConn(pArapConn);
  1396. }
  1397. // Do we need to free the allocated header packet?
  1398. if (!ATALK_SUCCESS(error) && (errorFreePkt))
  1399. {
  1400. AtalkNdisFreeBuf(pPktDesc);
  1401. }
  1402. return error;
  1403. }
  1404. VOID
  1405. AtalkDdpSendComplete(
  1406. NDIS_STATUS Status,
  1407. PBUFFER_DESC pBuffDesc,
  1408. PSEND_COMPL_INFO pInfo
  1409. )
  1410. /*++
  1411. Routine Description:
  1412. Arguments:
  1413. Return Value:
  1414. --*/
  1415. {
  1416. // Free up the buffer descriptor for the first part
  1417. // and call the specified completion. One of the contexts
  1418. // should be the remaining part of the buffer descriptor
  1419. // chain.
  1420. // There will always be atleast the ddp header, although the next
  1421. // part could be null. Thats upto the completion routine to care
  1422. // about.
  1423. ASSERT(pBuffDesc != NULL);
  1424. pBuffDesc->bd_Next = NULL;
  1425. ASSERT(pBuffDesc->bd_Flags & BD_CHAR_BUFFER);
  1426. AtalkNdisFreeBuf(pBuffDesc);
  1427. // If null, just return.
  1428. if (pInfo != NULL)
  1429. {
  1430. // Call the completion routine for the transmit if present
  1431. if (pInfo->sc_TransmitCompletion)
  1432. (pInfo->sc_TransmitCompletion)(Status, pInfo);
  1433. }
  1434. }
  1435. VOID
  1436. AtalkDdpInvokeHandlerBufDesc(
  1437. IN PPORT_DESCRIPTOR pPortDesc,
  1438. IN PDDP_ADDROBJ pDdpAddr,
  1439. IN PATALK_ADDR pSrc,
  1440. IN PATALK_ADDR pDest,
  1441. IN BYTE Protocol,
  1442. IN PBUFFER_DESC pBuffDesc OPTIONAL,
  1443. IN PBYTE pOptHdr OPTIONAL,
  1444. IN USHORT OptHdrLen OPTIONAL
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. Arguments:
  1449. Return Value:
  1450. --*/
  1451. {
  1452. USHORT pktLen = 0;
  1453. PBYTE pPkt = NULL;
  1454. BOOLEAN freePkt = FALSE;
  1455. // This is only called from directly or indirectly throught
  1456. // the router in AtalkDdpSend. Both of these cases indicate
  1457. // that we have completion routines to deal with. We just make
  1458. // a copy and assume caller will deal with its buffer descriptor.
  1459. // Alloc and copy the buffer descriptor data into pPkt.
  1460. // optimization: If the buffer descriptor is not a chain
  1461. // and contains a PBYTE and OptHdrLen = 0,
  1462. // then pass that directly.
  1463. // Or if buffer descriptor is NULL indicating 0-length
  1464. // sends.
  1465. do
  1466. {
  1467. if ((pBuffDesc != NULL) &&
  1468. (pBuffDesc->bd_Next == NULL) &&
  1469. (pBuffDesc->bd_Flags & BD_CHAR_BUFFER) &&
  1470. (OptHdrLen == 0))
  1471. {
  1472. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  1473. ("AtalkDdpInvokeHandlerBufDesc: one element, opt hdr null %ld\n",
  1474. pBuffDesc->bd_Length));
  1475. pPkt = pBuffDesc->bd_CharBuffer;
  1476. pktLen = pBuffDesc->bd_Length;
  1477. }
  1478. else if ((pBuffDesc != NULL) || (OptHdrLen != 0))
  1479. {
  1480. // Make a copy! Either the buffer descriptor of the Optional Header
  1481. // is non null. Or both or non-null.
  1482. if (pBuffDesc != NULL)
  1483. {
  1484. AtalkSizeOfBuffDescData(pBuffDesc, &pktLen);
  1485. ASSERT(pktLen > 0);
  1486. }
  1487. // Add the optHdrLen
  1488. pktLen += OptHdrLen;
  1489. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  1490. ("AtalkDdpInvokeHandlerBufDesc: Size (incl opt hdr len) %ld\n",
  1491. pktLen));
  1492. if ((pPkt = AtalkAllocMemory(pktLen)) != NULL)
  1493. {
  1494. // First copy the OptHdr if present
  1495. if (pOptHdr != NULL)
  1496. {
  1497. RtlCopyMemory(pPkt, pOptHdr, OptHdrLen);
  1498. }
  1499. if (pBuffDesc != NULL)
  1500. {
  1501. AtalkCopyBuffDescToBuffer(pBuffDesc,
  1502. 0, // SrcOff
  1503. pktLen - OptHdrLen,
  1504. pPkt + OptHdrLen);
  1505. }
  1506. freePkt = TRUE;
  1507. }
  1508. else
  1509. {
  1510. break;
  1511. }
  1512. }
  1513. else
  1514. {
  1515. ASSERT((pBuffDesc == NULL) && (OptHdrLen == 0));
  1516. ASSERT(pPkt == NULL);
  1517. ASSERT(pktLen == 0);
  1518. }
  1519. AtalkDdpInvokeHandler(pPortDesc,
  1520. pDdpAddr,
  1521. pSrc,
  1522. pDest,
  1523. Protocol,
  1524. pPkt,
  1525. pktLen);
  1526. } while (FALSE);
  1527. if (freePkt)
  1528. {
  1529. AtalkFreeMemory(pPkt);
  1530. }
  1531. }
  1532. VOID
  1533. AtalkDdpInvokeHandler(
  1534. IN PPORT_DESCRIPTOR pPortDesc,
  1535. IN PDDP_ADDROBJ pDdpAddr,
  1536. IN PATALK_ADDR pSrc,
  1537. IN PATALK_ADDR pDest,
  1538. IN BYTE Protocol,
  1539. IN PBYTE pPkt OPTIONAL,
  1540. IN USHORT PktLen OPTIONAL
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. Arguments:
  1545. Return Value:
  1546. --*/
  1547. {
  1548. PLIST_ENTRY p;
  1549. PDDP_READ pRead;
  1550. NTSTATUS status;
  1551. ATALK_ERROR error;
  1552. ULONG bytesCopied;
  1553. BOOLEAN eventDone = FALSE;
  1554. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  1555. // The address object should be referenced, and we just assume
  1556. // it will be valid during the lifetime of this call.
  1557. // Check if protocol type is valid.
  1558. if ((pDdpAddr->ddpao_Protocol != Protocol) &&
  1559. (pDdpAddr->ddpao_Protocol != DDPPROTO_ANY))
  1560. {
  1561. return;
  1562. }
  1563. // First check for queued ddp reads
  1564. ACQUIRE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  1565. if (!IsListEmpty(&pDdpAddr->ddpao_ReadLinkage))
  1566. {
  1567. p = RemoveHeadList(&pDdpAddr->ddpao_ReadLinkage);
  1568. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  1569. error = ATALK_NO_ERROR;
  1570. pRead = CONTAINING_RECORD(p, DDP_READ, dr_Linkage);
  1571. // Do copy if > 0 bytes
  1572. if (PktLen > 0)
  1573. {
  1574. if (PktLen > pRead->dr_OpBufLen)
  1575. {
  1576. error = ATALK_BUFFER_TOO_SMALL;
  1577. }
  1578. PktLen = MIN(PktLen, pRead->dr_OpBufLen);
  1579. status = TdiCopyBufferToMdl(pPkt,
  1580. 0,
  1581. PktLen,
  1582. GET_MDL_FROM_OPAQUE(pRead->dr_OpBuf),
  1583. 0,
  1584. &bytesCopied);
  1585. ASSERT(status == STATUS_SUCCESS);
  1586. }
  1587. (*pRead->dr_RcvCmp)(error, pRead->dr_OpBuf, PktLen, pSrc, pRead->dr_RcvCtx);
  1588. AtalkFreeMemory(pRead);
  1589. return;
  1590. }
  1591. // If a handler was set on this socket,call it.
  1592. else if (pDdpAddr->ddpao_Handler != NULL)
  1593. {
  1594. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  1595. (*pDdpAddr->ddpao_Handler)(pPortDesc,
  1596. pDdpAddr,
  1597. pPkt,
  1598. PktLen,
  1599. pSrc,
  1600. pDest,
  1601. ATALK_NO_ERROR,
  1602. Protocol,
  1603. pDdpAddr->ddpao_HandlerCtx,
  1604. FALSE,
  1605. NULL);
  1606. }
  1607. else
  1608. {
  1609. // if there is an event handler on this address object call it.
  1610. // If there is already a buffered datagram, drop this packet.
  1611. // If not, save this datagram as the buffered one, and then
  1612. // indicate,
  1613. if (pDdpAddr->ddpao_Flags & DDPAO_DGRAM_EVENT)
  1614. {
  1615. do
  1616. {
  1617. // We have datagram event handler set on this AO.
  1618. if (pDdpAddr->ddpao_Flags & (DDPAO_DGRAM_ACTIVE |
  1619. DDPAO_DGRAM_PENDING))
  1620. {
  1621. // We are already indicating an event. Or we
  1622. // have a buffered datagram. Drop this pkt.
  1623. break;
  1624. }
  1625. else
  1626. {
  1627. PTDI_IND_RECEIVE_DATAGRAM RcvHandler;
  1628. PVOID RcvCtx;
  1629. ULONG bytesTaken;
  1630. PIRP rcvDgramIrp;
  1631. TA_APPLETALK_ADDRESS srcTdiAddr;
  1632. NTSTATUS status;
  1633. ASSERT(pDdpAddr->ddpao_EventInfo != NULL);
  1634. pDdpAddr->ddpao_Flags |= (DDPAO_DGRAM_ACTIVE |
  1635. DDPAO_DGRAM_PENDING);
  1636. RcvHandler = pDdpAddr->ddpao_EventInfo->ev_RcvDgramHandler;
  1637. RcvCtx = pDdpAddr->ddpao_EventInfo->ev_RcvDgramCtx;
  1638. ATALKADDR_TO_TDI(&srcTdiAddr, pSrc);
  1639. // Save the dgram in the event info.
  1640. RtlCopyMemory(pDdpAddr->ddpao_EventInfo->ev_IndDgram, pPkt, PktLen);
  1641. pDdpAddr->ddpao_EventInfo->ev_IndDgramLen = PktLen;
  1642. pDdpAddr->ddpao_EventInfo->ev_IndSrc = *pSrc;
  1643. pDdpAddr->ddpao_EventInfo->ev_IndProto = Protocol;
  1644. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  1645. status = (*RcvHandler)(RcvCtx,
  1646. sizeof(TA_APPLETALK_ADDRESS),
  1647. &srcTdiAddr,
  1648. 0, // Options length
  1649. NULL, // Options
  1650. 0, // Datagram flags
  1651. (ULONG)PktLen, // Bytes indicated
  1652. (ULONG)PktLen, // Bytes available
  1653. (ULONG *)&bytesTaken,
  1654. pPkt,
  1655. &rcvDgramIrp);
  1656. ASSERT((bytesTaken == 0) || (bytesTaken == PktLen));
  1657. if (status == STATUS_MORE_PROCESSING_REQUIRED)
  1658. {
  1659. if (rcvDgramIrp != NULL)
  1660. {
  1661. // Post the receive as if it came from the io system
  1662. status= AtalkDispatchInternalDeviceControl(
  1663. (PDEVICE_OBJECT)AtalkDeviceObject[ATALK_DEV_DDP],
  1664. rcvDgramIrp);
  1665. ASSERT(status == STATUS_PENDING);
  1666. }
  1667. }
  1668. else if (status == STATUS_SUCCESS)
  1669. {
  1670. if (bytesTaken != 0)
  1671. {
  1672. // Assume all of the data was read.
  1673. pDdpAddr->ddpao_Flags &= ~DDPAO_DGRAM_PENDING;
  1674. }
  1675. }
  1676. else if (status == STATUS_DATA_NOT_ACCEPTED)
  1677. {
  1678. // Client may have posted a receive in the indication. Or
  1679. // it will post a receive later on. Do nothing here.
  1680. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  1681. ("atalkDdpRecvData: Indication status %lx\n", status));
  1682. }
  1683. ACQUIRE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  1684. }
  1685. } while (FALSE);
  1686. // reset the event flags
  1687. pDdpAddr->ddpao_Flags &= ~DDPAO_DGRAM_ACTIVE;
  1688. }
  1689. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  1690. }
  1691. }
  1692. VOID
  1693. AtalkDdpPacketIn(
  1694. IN PPORT_DESCRIPTOR pPortDesc,
  1695. IN PBYTE pLinkHdr,
  1696. IN PBYTE pPkt,
  1697. IN USHORT PktLen,
  1698. IN BOOLEAN fWanPkt
  1699. )
  1700. /*++
  1701. Routine Description:
  1702. Arguments:
  1703. Return Value:
  1704. --*/
  1705. {
  1706. USHORT dgramLen, ddpHdrLen;
  1707. USHORT hopCnt, checksum;
  1708. BYTE Protocol;
  1709. ATALK_ADDR destAddr, srcAddr;
  1710. PBYTE pDdpHdr;
  1711. // Only for localtalk
  1712. BYTE alapSrcNode;
  1713. BYTE alapDestNode;
  1714. PBUFFER_DESC pBufCopy = NULL;
  1715. SEND_COMPL_INFO SendInfo;
  1716. PBYTE pOrgPkt;
  1717. USHORT srcOffset;
  1718. BOOLEAN extHdr = TRUE;
  1719. PBYTE pRouteInfo;
  1720. USHORT routeLen = 0;
  1721. BOOLEAN delivered = FALSE;
  1722. BOOLEAN broadcast = FALSE;
  1723. BOOLEAN shouldBeRouted = FALSE;
  1724. BOOLEAN sendOnDefAdptr = FALSE;
  1725. ATALK_ERROR error = ATALK_NO_ERROR;
  1726. KIRQL OldIrql;
  1727. TIME TimeS, TimeE, TimeD;
  1728. TimeS = KeQueryPerformanceCounter(NULL);
  1729. if (PORT_CLOSING(pPortDesc))
  1730. {
  1731. // If we are not active, return!
  1732. return;
  1733. }
  1734. // save the packet starting
  1735. pOrgPkt = pPkt;
  1736. do
  1737. {
  1738. ASSERT((PktLen > 0) || ((PktLen == 0) && (pPkt == NULL)));
  1739. if (PktLen > (MAX_DGRAM_SIZE + LDDP_HDR_LEN))
  1740. {
  1741. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_WARN,
  1742. ("AtalkDdpPacketIn: Invalid size %lx\n", PktLen));
  1743. error = ATALK_DDP_INVALID_LEN;
  1744. break;
  1745. }
  1746. // Get to the ddp header
  1747. pDdpHdr = pPkt;
  1748. // Short and long header formats have the length in the same place,
  1749. dgramLen = DDP_GET_LEN(pDdpHdr);
  1750. hopCnt = DDP_GET_HOP_COUNT(pDdpHdr);
  1751. // Is the packet too long?
  1752. if ((hopCnt > RTMP_MAX_HOPS) || (dgramLen > PktLen))
  1753. {
  1754. error = ATALK_DDP_INVALID_LEN;
  1755. break;
  1756. }
  1757. // First glean the information. Check for route info if
  1758. // tokenring network.
  1759. switch (pPortDesc->pd_NdisPortType)
  1760. {
  1761. case NdisMedium802_5:
  1762. if (pLinkHdr[TLAP_SRC_OFFSET] & TLAP_SRC_ROUTING_MASK)
  1763. {
  1764. routeLen = (pLinkHdr[TLAP_ROUTE_INFO_OFFSET] & TLAP_ROUTE_INFO_SIZE_MASK);
  1765. // First, glean any AARP information that we can, then handle the DDP
  1766. // packet. This guy also makes sure we have a good 802.2 header...
  1767. //
  1768. // Need to make a localcopy of the source address and then turn
  1769. // the source routing bit off before calling GleanAarpInfo
  1770. //
  1771. pLinkHdr[TLAP_SRC_OFFSET] &= ~TLAP_SRC_ROUTING_MASK;
  1772. pRouteInfo = pLinkHdr + TLAP_ROUTE_INFO_OFFSET;
  1773. }
  1774. ddpHdrLen = LDDP_HDR_LEN;
  1775. srcOffset = TLAP_SRC_OFFSET;
  1776. break;
  1777. case NdisMedium802_3:
  1778. // Check the length.
  1779. if ((dgramLen < LDDP_HDR_LEN) ||
  1780. (dgramLen > MAX_DGRAM_SIZE + LDDP_HDR_LEN))
  1781. {
  1782. error = ATALK_DDP_INVALID_LEN;
  1783. break;
  1784. }
  1785. ddpHdrLen = LDDP_HDR_LEN;
  1786. srcOffset = ELAP_SRC_OFFSET;
  1787. break;
  1788. case NdisMediumFddi:
  1789. // Check the length.
  1790. if ((dgramLen < LDDP_HDR_LEN) ||
  1791. (dgramLen > MAX_DGRAM_SIZE + LDDP_HDR_LEN))
  1792. {
  1793. error = ATALK_DDP_INVALID_LEN;
  1794. break;
  1795. }
  1796. ddpHdrLen = LDDP_HDR_LEN;
  1797. srcOffset = FDDI_SRC_OFFSET;
  1798. break;
  1799. case NdisMediumLocalTalk:
  1800. // Do we have an extended header?
  1801. extHdr = (BOOLEAN)(pLinkHdr[ALAP_TYPE_OFFSET] == ALAP_LDDP_HDR_TYPE);
  1802. if (extHdr)
  1803. {
  1804. ddpHdrLen = LDDP_HDR_LEN;
  1805. }
  1806. else
  1807. {
  1808. alapDestNode = *(pLinkHdr + ALAP_DEST_OFFSET);
  1809. alapSrcNode = *(pLinkHdr + ALAP_SRC_OFFSET);
  1810. if ((dgramLen < SDDP_HDR_LEN) ||
  1811. (dgramLen > (MAX_DGRAM_SIZE + SDDP_HDR_LEN)))
  1812. {
  1813. error = ATALK_DDP_INVALID_LEN;
  1814. break;
  1815. }
  1816. ddpHdrLen = SDDP_HDR_LEN;
  1817. }
  1818. break;
  1819. case NdisMediumWan:
  1820. // Check the length.
  1821. if ((dgramLen < LDDP_HDR_LEN) ||
  1822. (dgramLen > MAX_DGRAM_SIZE + LDDP_HDR_LEN))
  1823. {
  1824. error = ATALK_DDP_INVALID_LEN;
  1825. break;
  1826. }
  1827. ddpHdrLen = LDDP_HDR_LEN;
  1828. extHdr = TRUE; // always extended for ARAP
  1829. break;
  1830. default:
  1831. // Should never happen!
  1832. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_FATAL,
  1833. ("AtalkDdpPacketIn: Unknown media\n"));
  1834. KeBugCheck(0);
  1835. break;
  1836. }
  1837. if (!ATALK_SUCCESS(error))
  1838. {
  1839. break;
  1840. }
  1841. // Advance packet to point to the data. Caller frees up packet.
  1842. pPkt += ddpHdrLen;
  1843. // Glean aarp information for non-localtalk and non-RAS ports
  1844. if ((pPortDesc->pd_NdisPortType != NdisMediumLocalTalk) && !fWanPkt)
  1845. {
  1846. AtalkAarpGleanInfo(pPortDesc,
  1847. pLinkHdr + srcOffset,
  1848. TLAP_ADDR_LEN,
  1849. pRouteInfo,
  1850. (USHORT)routeLen,
  1851. pDdpHdr,
  1852. (USHORT)ddpHdrLen);
  1853. }
  1854. pDdpHdr += 2; // Past off-cable & len
  1855. if (extHdr) // Long DDP header
  1856. {
  1857. // Get checksum, verification, if needed.
  1858. GETSHORT2SHORT(&checksum, pDdpHdr);
  1859. pDdpHdr += 2;
  1860. if (checksum != 0)
  1861. {
  1862. USHORT calcCheckSum;
  1863. // pDdpHdr has already moved passed LEADING_UNCHECKSUMED_BYTES.
  1864. // So we just need to decrease the header length field. Use
  1865. // dgramLen, NOT PktLen!
  1866. calcCheckSum = AtalkDdpCheckSumPacket(pDdpHdr,
  1867. (USHORT)(ddpHdrLen - LEADING_UNCHECKSUMED_BYTES),
  1868. pPkt,
  1869. (USHORT)(dgramLen - ddpHdrLen));
  1870. if (checksum != calcCheckSum)
  1871. {
  1872. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  1873. ("AtalkDdpPacketIn: Checksums dont match! %lx.%lx\n",
  1874. checksum, calcCheckSum));
  1875. AtalkLogBadPacket(pPortDesc,
  1876. &srcAddr,
  1877. &destAddr,
  1878. pDdpHdr,
  1879. (USHORT)(ddpHdrLen - LEADING_UNCHECKSUMED_BYTES));
  1880. error = ATALK_DDP_PKT_DROPPED;
  1881. break;
  1882. }
  1883. }
  1884. // Build full source and destination AppleTalk address structures
  1885. // from our DDP header.
  1886. GETSHORT2SHORT(&destAddr.ata_Network, pDdpHdr);
  1887. pDdpHdr += 2;
  1888. GETSHORT2SHORT(&srcAddr.ata_Network, pDdpHdr);
  1889. pDdpHdr += 2;
  1890. destAddr.ata_Node = *pDdpHdr++;
  1891. srcAddr.ata_Node = *pDdpHdr++;
  1892. destAddr.ata_Socket = *pDdpHdr++;
  1893. srcAddr.ata_Socket = *pDdpHdr++;
  1894. // Get the protocol type.
  1895. Protocol = *pDdpHdr;
  1896. broadcast = (destAddr.ata_Node == ATALK_BROADCAST_NODE);
  1897. // Do we like what we see? Note "nnnn00" is now allowed and used by
  1898. // NBP.
  1899. if ((srcAddr.ata_Network > LAST_VALID_NETWORK) ||
  1900. (srcAddr.ata_Network < FIRST_VALID_NETWORK) ||
  1901. (srcAddr.ata_Node < MIN_USABLE_ATALKNODE) ||
  1902. (srcAddr.ata_Node > MAX_USABLE_ATALKNODE))
  1903. {
  1904. error = ATALK_DDP_INVALID_SRC;
  1905. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  1906. ("DdpPacketIn: Received pkt with bad src addr %lx.%lx\n",
  1907. srcAddr.ata_Network,srcAddr.ata_Node));
  1908. break;
  1909. }
  1910. if ((destAddr.ata_Network > LAST_VALID_NETWORK) ||
  1911. ((destAddr.ata_Node > MAX_USABLE_ATALKNODE) &&
  1912. !broadcast))
  1913. {
  1914. error = ATALK_DDP_INVALID_DEST;
  1915. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  1916. ("DdpPacketIn: Received pkt with bad src addr %lx.%lx\n",
  1917. destAddr.ata_Network,destAddr.ata_Node));
  1918. break;
  1919. }
  1920. // Loop through all nodes that are on the reception port and see if
  1921. // anybody wants this packet. The algorithm is from the "AppleTalk
  1922. // Phase 2 Protocol Specification" with enhacements to support ports
  1923. // that have multiple nodes.
  1924. // "0000xx" (where "xx" isnt "FF") should not be accepted on an
  1925. // extended port... For some unknown reason, the spec would like
  1926. // us to pass this case onto the router (which will, no doubt,
  1927. // drop it on the floor because it won't find network zero in its
  1928. // routing table)... you know, bug-for-bug compatible!
  1929. if ((destAddr.ata_Network == UNKNOWN_NETWORK) &&
  1930. (pPortDesc->pd_Flags & PD_EXT_NET) &&
  1931. (!broadcast))
  1932. {
  1933. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  1934. ("DdpPacketIn: Received pkt with net/node %lx.%lx on ext\n",
  1935. destAddr.ata_Network, destAddr.ata_Node));
  1936. shouldBeRouted = TRUE;
  1937. }
  1938. else
  1939. {
  1940. //
  1941. // if we have RAS port configured, and currently have dial-in
  1942. // client(s) connected then see if any (or all) of them are
  1943. // interested in this packet
  1944. // Make sure that any broadcasts we forward came on default port
  1945. //
  1946. if ( (RasPortDesc) &&
  1947. ((!broadcast) ||
  1948. (broadcast && (pPortDesc == AtalkDefaultPort))) )
  1949. {
  1950. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  1951. if (!IsListEmpty(&RasPortDesc->pd_PPPConnHead))
  1952. {
  1953. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  1954. // see if any PPP client(s) are interested
  1955. PPPRoutePacketToWan(
  1956. &destAddr,
  1957. &srcAddr,
  1958. Protocol,
  1959. pPkt, // only data, no DDP hdr
  1960. (USHORT)(dgramLen - ddpHdrLen), // only data length
  1961. hopCnt,
  1962. broadcast,
  1963. &delivered);
  1964. //
  1965. // if we delivered it to any of the PPP clients, and
  1966. // this was not a broadcast, then we 're done here
  1967. //
  1968. if (delivered && !broadcast)
  1969. {
  1970. break;
  1971. }
  1972. }
  1973. else
  1974. {
  1975. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  1976. }
  1977. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  1978. if (!IsListEmpty(&RasPortDesc->pd_ArapConnHead))
  1979. {
  1980. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  1981. // see if any ARAP client(s) are interested
  1982. ArapRoutePacketToWan(
  1983. &destAddr,
  1984. &srcAddr,
  1985. Protocol,
  1986. pOrgPkt, // whole packet (with DDP hdr)
  1987. dgramLen, // whole packet length
  1988. broadcast,
  1989. &delivered);
  1990. //
  1991. // if we delivered it to any of the ARAP clients, and
  1992. // this was not a broadcast, then we 're done here
  1993. //
  1994. if (delivered && !broadcast)
  1995. {
  1996. break;
  1997. }
  1998. }
  1999. else
  2000. {
  2001. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  2002. }
  2003. }
  2004. // Now, on the packet in path, we either deliver the packet
  2005. // to one of our nodes on this port, or we pass it on to the
  2006. // router. Even if the packet is a broadcast, the delivered
  2007. // flag will be set to true. shouldBeRouter will be set to
  2008. // true, only if the packet *DOES NOT* seem to be destined for
  2009. // this port. We route the packet *ONLY IF* shouldBeRouter
  2010. // is true
  2011. AtalkDdpInPktToNodesOnPort(pPortDesc,
  2012. &destAddr,
  2013. &srcAddr,
  2014. Protocol,
  2015. pPkt,
  2016. (USHORT)(dgramLen - LDDP_HDR_LEN),
  2017. &shouldBeRouted);
  2018. }
  2019. //
  2020. // if this packet originated from a dial-in client and the packet wasn't
  2021. // claimed by any of our nodes then we need to send it over to the LAN net:
  2022. // see if we must
  2023. //
  2024. if (fWanPkt)
  2025. {
  2026. sendOnDefAdptr = FALSE;
  2027. //
  2028. // broadcasts are meant for the local net, so default adapter only
  2029. //
  2030. if (broadcast)
  2031. {
  2032. sendOnDefAdptr = TRUE;
  2033. }
  2034. //
  2035. // if destination is on the same net as the default adapter, or
  2036. // if the router is not running then send it on the default adapter
  2037. //
  2038. if (shouldBeRouted)
  2039. {
  2040. if ((WITHIN_NETWORK_RANGE(destAddr.ata_Network,
  2041. &pPortDesc->pd_NetworkRange)) ||
  2042. (!(pPortDesc->pd_Flags & PD_ROUTER_RUNNING)))
  2043. {
  2044. sendOnDefAdptr = TRUE;
  2045. }
  2046. }
  2047. //
  2048. // ok, we must send it on the default adapter.
  2049. //
  2050. if (sendOnDefAdptr)
  2051. {
  2052. // no need to send this packet to router: we're sending here
  2053. shouldBeRouted = FALSE;
  2054. pBufCopy = AtalkAllocBuffDesc(
  2055. NULL,
  2056. (USHORT)(dgramLen - LDDP_HDR_LEN),
  2057. (BD_FREE_BUFFER | BD_CHAR_BUFFER));
  2058. if (pBufCopy == NULL)
  2059. {
  2060. error = ATALK_RESR_MEM;
  2061. break;
  2062. }
  2063. AtalkCopyBufferToBuffDesc(pPkt,
  2064. (USHORT)(dgramLen - LDDP_HDR_LEN),
  2065. pBufCopy,
  2066. 0);
  2067. SendInfo.sc_TransmitCompletion = atalkDdpRouteComplete;
  2068. SendInfo.sc_Ctx1 = pPortDesc;
  2069. SendInfo.sc_Ctx3 = NULL;
  2070. SendInfo.sc_Ctx2 = pBufCopy;
  2071. error = AtalkDdpTransmit(pPortDesc,
  2072. &srcAddr,
  2073. &destAddr,
  2074. Protocol,
  2075. pBufCopy,
  2076. NULL,
  2077. 0,
  2078. 0,
  2079. NULL,
  2080. NULL,
  2081. &SendInfo);
  2082. if (error != ATALK_PENDING)
  2083. {
  2084. AtalkFreeBuffDesc(pBufCopy);
  2085. break;
  2086. }
  2087. }
  2088. }
  2089. //
  2090. // if we still haven't been able to deliver the packet, and if we
  2091. // have routing enabled, give router a crack at it
  2092. //
  2093. if (shouldBeRouted && pPortDesc->pd_Flags & PD_ROUTER_RUNNING)
  2094. {
  2095. AtalkDdpRouteInPkt(pPortDesc,
  2096. &srcAddr,
  2097. &destAddr,
  2098. Protocol,
  2099. pPkt,
  2100. (USHORT)(dgramLen - LDDP_HDR_LEN),
  2101. hopCnt);
  2102. }
  2103. }
  2104. else // Short DDP header!
  2105. {
  2106. BYTE ThisNode;
  2107. ASSERT(!EXT_NET(pPortDesc));
  2108. if (pPortDesc->pd_Flags & PD_EXT_NET)
  2109. {
  2110. error = ATALK_DDP_SHORT_HDR;
  2111. break;
  2112. }
  2113. // Use network number for the node on this port for source/destination
  2114. // network numbers. When we search for the socket/address
  2115. // object, the concept net = 0, matches anything will come
  2116. // into play.
  2117. srcAddr.ata_Network = destAddr.ata_Network = NET_ON_NONEXTPORT(pPortDesc);
  2118. srcAddr.ata_Node = alapSrcNode;
  2119. ThisNode = NODE_ON_NONEXTPORT(pPortDesc);
  2120. if (alapDestNode == ATALK_BROADCAST_NODE)
  2121. {
  2122. destAddr.ata_Node = ThisNode;
  2123. }
  2124. else if (alapDestNode != ThisNode)
  2125. {
  2126. error = ATALK_DDP_INVALID_DEST;
  2127. break;
  2128. }
  2129. else
  2130. {
  2131. destAddr.ata_Node = alapDestNode;
  2132. }
  2133. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_WARN,
  2134. ("AtalkDdpPacketIn: NonExtended Dest Net.Node %lx.%lx\n",
  2135. destAddr.ata_Network, destAddr.ata_Node));
  2136. // Get the socket numbers from the ddp header.
  2137. destAddr.ata_Socket = *pDdpHdr++;
  2138. srcAddr.ata_Socket = *pDdpHdr++;
  2139. // Get the protocol type
  2140. Protocol = *pDdpHdr;
  2141. // If the protocol type is 0, we have an error.
  2142. if (Protocol == 0)
  2143. {
  2144. error = ATALK_DDP_INVALID_PROTO;
  2145. break;
  2146. }
  2147. // Now the destination node address could be
  2148. // ALAP_BROADCAST_NODE (0xFF).
  2149. if ((srcAddr.ata_Node < MIN_USABLE_ATALKNODE) ||
  2150. (srcAddr.ata_Node > MAX_USABLE_ATALKNODE))
  2151. {
  2152. error = ATALK_DDP_INVALID_SRC;
  2153. break;
  2154. }
  2155. if (((destAddr.ata_Node < MIN_USABLE_ATALKNODE) ||
  2156. (destAddr.ata_Node > MAX_USABLE_ATALKNODE)) &&
  2157. (destAddr.ata_Node != ATALK_BROADCAST_NODE))
  2158. {
  2159. error = ATALK_DDP_INVALID_DEST;
  2160. break;
  2161. }
  2162. // On a non-extended port, there will be only one node.
  2163. AtalkDdpInPktToNodesOnPort(pPortDesc,
  2164. &destAddr,
  2165. &srcAddr,
  2166. Protocol,
  2167. pPkt,
  2168. (USHORT)(dgramLen - SDDP_HDR_LEN),
  2169. &shouldBeRouted); // This is a dud parameter
  2170. // for non-ext nets
  2171. }
  2172. } while (FALSE);
  2173. if (!ATALK_SUCCESS(error))
  2174. {
  2175. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_WARN,
  2176. ("AtalkDdpPacketIn: Dropping packet %lx\n", error) );
  2177. }
  2178. TimeE = KeQueryPerformanceCounter(NULL);
  2179. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  2180. INTERLOCKED_ADD_LARGE_INTGR_DPC(
  2181. &pPortDesc->pd_PortStats.prtst_DdpPacketInProcessTime,
  2182. TimeD,
  2183. &AtalkStatsLock.SpinLock);
  2184. INTERLOCKED_INCREMENT_LONG_DPC(
  2185. &pPortDesc->pd_PortStats.prtst_NumDdpPacketsIn,
  2186. &AtalkStatsLock.SpinLock);
  2187. }
  2188. VOID
  2189. AtalkDdpQuery(
  2190. IN PDDP_ADDROBJ pDdpAddr,
  2191. IN PAMDL pAmdl,
  2192. OUT PULONG BytesWritten
  2193. )
  2194. /*++
  2195. Routine Description:
  2196. Arguments:
  2197. Return Value:
  2198. --*/
  2199. {
  2200. TDI_ADDRESS_INFO tdiInfo;
  2201. PTA_APPLETALK_ADDRESS pTaAddr;
  2202. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  2203. pTaAddr = (PTA_APPLETALK_ADDRESS)&tdiInfo.Address;
  2204. ATALKADDR_TO_TDI(pTaAddr, &pDdpAddr->ddpao_Addr);
  2205. TdiCopyBufferToMdl ((PBYTE)&tdiInfo,
  2206. 0L,
  2207. sizeof(tdiInfo),
  2208. pAmdl,
  2209. 0,
  2210. BytesWritten);
  2211. }
  2212. VOID
  2213. AtalkDdpOutBufToNodesOnPort(
  2214. IN PPORT_DESCRIPTOR pPortDesc,
  2215. IN PATALK_ADDR pSrc,
  2216. IN PATALK_ADDR pDest,
  2217. IN BYTE Protocol,
  2218. IN PBUFFER_DESC pBuffDesc OPTIONAL,
  2219. IN PBYTE pOptHdr OPTIONAL,
  2220. IN USHORT OptHdrLen OPTIONAL,
  2221. OUT PBOOLEAN Delivered
  2222. )
  2223. /*++
  2224. Routine Description:
  2225. Arguments:
  2226. Return Value:
  2227. --*/
  2228. {
  2229. ATALK_ERROR error;
  2230. PATALK_NODE pAtalkNode, pNextNode;
  2231. PDDP_ADDROBJ pDdpAddr;
  2232. BOOLEAN fDeliver, fSpecific, needToRef;
  2233. BOOLEAN lockHeld = FALSE;
  2234. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  2235. // Do not internally loopback broadcast frames, these should come
  2236. // back to us from the mac.
  2237. if (pDest->ata_Node == ATALK_BROADCAST_NODE)
  2238. {
  2239. *Delivered = FALSE;
  2240. return;
  2241. }
  2242. fSpecific = (pDest->ata_Network != CABLEWIDE_BROADCAST_NETWORK);
  2243. // Walk through our nodes to see if we can deliver this packet.
  2244. // OPTIMIZATIONS:
  2245. // In most cases, this will not be true. Optimize for returning false.
  2246. // Also, a node closing is a rare occurence. If we run into one that is
  2247. // closing, we abort trying to deliver this packet to a node on our port,
  2248. // and instead return delivered = FALSE. DDP - unreliable, and node closing
  2249. // should be a transient state. We avoid the acquire/release code.
  2250. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2251. lockHeld = TRUE;
  2252. pNextNode = pPortDesc->pd_Nodes;
  2253. needToRef = TRUE;
  2254. for (; (pAtalkNode = pNextNode) != NULL; )
  2255. {
  2256. fDeliver = FALSE;
  2257. error = ATALK_NO_ERROR;
  2258. if (((pAtalkNode->an_NodeAddr.atn_Network == pDest->ata_Network) ||
  2259. !fSpecific) &&
  2260. (pAtalkNode->an_NodeAddr.atn_Node == pDest->ata_Node))
  2261. {
  2262. // Reference node. If we fail, we abort.
  2263. if (needToRef)
  2264. {
  2265. AtalkNodeRefByPtr(pAtalkNode, &error);
  2266. }
  2267. if (ATALK_SUCCESS(error))
  2268. {
  2269. fDeliver = TRUE;
  2270. // Set up for next node.
  2271. if (fSpecific)
  2272. {
  2273. pNextNode = NULL;
  2274. }
  2275. else
  2276. {
  2277. // Get next eligible node.
  2278. pNextNode = pAtalkNode->an_Next;
  2279. while (pNextNode != NULL)
  2280. {
  2281. if (pNextNode->an_NodeAddr.atn_Node == pDest->ata_Node)
  2282. {
  2283. AtalkNodeRefByPtr(pNextNode, &error);
  2284. if (!ATALK_SUCCESS(error))
  2285. {
  2286. pNextNode = NULL;
  2287. }
  2288. needToRef = FALSE;
  2289. break;
  2290. }
  2291. else
  2292. {
  2293. pNextNode = pNextNode->an_Next;
  2294. }
  2295. }
  2296. }
  2297. }
  2298. else
  2299. {
  2300. // Break out of the for loop.
  2301. break;
  2302. }
  2303. }
  2304. else
  2305. {
  2306. pNextNode = pAtalkNode->an_Next;
  2307. needToRef = TRUE;
  2308. }
  2309. if (fDeliver)
  2310. {
  2311. // Release port lock, deliver packet, and Deref the node.
  2312. // Find the ddp address object on this node corresponding
  2313. // to this address. This will get the node lock.
  2314. AtalkDdpRefByAddrNode(pPortDesc,
  2315. pDest,
  2316. pAtalkNode,
  2317. &pDdpAddr,
  2318. &error);
  2319. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2320. lockHeld = FALSE;
  2321. if (ATALK_SUCCESS(error))
  2322. {
  2323. // Invoke socket handler on this address object.
  2324. AtalkDdpInvokeHandlerBufDesc(pPortDesc,
  2325. pDdpAddr,
  2326. pSrc,
  2327. pDest,
  2328. Protocol,
  2329. pBuffDesc,
  2330. pOptHdr,
  2331. OptHdrLen);
  2332. // Remove the reference on the socket
  2333. AtalkDdpDereferenceDpc(pDdpAddr);
  2334. }
  2335. // Remove the reference on the node
  2336. AtalkNodeDereference(pAtalkNode);
  2337. // If we had to deliver to a specific node, we are done.
  2338. if (fSpecific)
  2339. {
  2340. break;
  2341. }
  2342. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2343. lockHeld = TRUE;
  2344. }
  2345. }
  2346. if (lockHeld)
  2347. {
  2348. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2349. }
  2350. *Delivered = (fSpecific && fDeliver);
  2351. }
  2352. VOID
  2353. AtalkDdpInPktToNodesOnPort(
  2354. IN PPORT_DESCRIPTOR pPortDesc,
  2355. IN PATALK_ADDR pDest,
  2356. IN PATALK_ADDR pSrc,
  2357. IN BYTE Protocol,
  2358. IN PBYTE pPkt OPTIONAL,
  2359. IN USHORT PktLen OPTIONAL,
  2360. OUT PBOOLEAN ShouldBeRouted
  2361. )
  2362. /*++
  2363. Routine Description:
  2364. Arguments:
  2365. Return Value:
  2366. --*/
  2367. {
  2368. PATALK_NODE pAtalkNode, pNextNode;
  2369. PDDP_ADDROBJ pDdpAddr;
  2370. BOOLEAN broadcast;
  2371. BOOLEAN fSpecific, fDeliver, needToRef;
  2372. ATALK_ERROR error = ATALK_NO_ERROR;
  2373. BOOLEAN lockHeld = FALSE;
  2374. BOOLEAN shouldBeRouted = FALSE;
  2375. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  2376. broadcast = (pDest->ata_Node == ATALK_BROADCAST_NODE);
  2377. // is a directed packet to a socket on a particular node...?
  2378. fSpecific = (!broadcast &&
  2379. (pDest->ata_Network != UNKNOWN_NETWORK));
  2380. // OPTIMIZATIONS:
  2381. // In most cases, this will not be true. Optimize for returning false.
  2382. // Also, a node closing is a rare occurence. If we run into one that is
  2383. // closing, we abort trying to deliver this packet to a node on our port,
  2384. // and instead return delivered = FALSE. DDP - unreliable, and node closing
  2385. // should be a transient state. We avoid the acquire/release code.
  2386. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2387. lockHeld = TRUE;
  2388. pNextNode = pPortDesc->pd_Nodes;
  2389. needToRef = TRUE;
  2390. while ((pAtalkNode = pNextNode) != NULL)
  2391. {
  2392. fDeliver = FALSE;
  2393. error = ATALK_NO_ERROR;
  2394. // For incoming packet, we check to see if the destination
  2395. // net is 0, or destination net is our node's net, or we are
  2396. // non-extended and our node's net is zero. i.e. is the packet
  2397. // destined for a node on this port. If not, route it. Continue
  2398. // checking all nodes though, as a single port can have nodes with
  2399. // different network numbers.
  2400. if (((pAtalkNode->an_NodeAddr.atn_Network == pDest->ata_Network) ||
  2401. (pDest->ata_Network == UNKNOWN_NETWORK) ||
  2402. (!EXT_NET(pPortDesc) &&
  2403. (pAtalkNode->an_NodeAddr.atn_Network == UNKNOWN_NETWORK))) &&
  2404. (broadcast || (pAtalkNode->an_NodeAddr.atn_Node == pDest->ata_Node)))
  2405. {
  2406. // Reference node if we need to. Only happens for the first
  2407. // time we enter the loop. If we fail, we abort.
  2408. if (needToRef)
  2409. {
  2410. AtalkNodeRefByPtr(pAtalkNode, &error);
  2411. if (!ATALK_SUCCESS(error))
  2412. {
  2413. break;
  2414. }
  2415. }
  2416. fDeliver = TRUE;
  2417. // Set up for next node.
  2418. if (fSpecific)
  2419. {
  2420. // Only one node on a non-extended port. So set next to NULL.
  2421. pNextNode = NULL;
  2422. }
  2423. else
  2424. {
  2425. // Get next eligible node.
  2426. pNextNode = pAtalkNode->an_Next;
  2427. while (pNextNode != NULL)
  2428. {
  2429. if (((pNextNode->an_NodeAddr.atn_Network == pDest->ata_Network) ||
  2430. (pDest->ata_Network == UNKNOWN_NETWORK) ||
  2431. (!EXT_NET(pPortDesc) &&
  2432. (pNextNode->an_NodeAddr.atn_Network == UNKNOWN_NETWORK))) &&
  2433. (broadcast ||
  2434. (pNextNode->an_NodeAddr.atn_Node == pDest->ata_Node)))
  2435. {
  2436. AtalkNodeRefByPtr(pNextNode, &error);
  2437. if (!ATALK_SUCCESS(error))
  2438. {
  2439. pNextNode = NULL;
  2440. }
  2441. needToRef = FALSE;
  2442. break;
  2443. }
  2444. pNextNode = pNextNode->an_Next;
  2445. }
  2446. }
  2447. }
  2448. else
  2449. {
  2450. // The packet probably could be meant to be routed.
  2451. // This could be set multiple times - idempotent.
  2452. shouldBeRouted = TRUE;
  2453. needToRef = TRUE;
  2454. pNextNode = pAtalkNode->an_Next;
  2455. }
  2456. if (fDeliver)
  2457. {
  2458. // Release port lock, deliver packet, and Deref the node.
  2459. // Find the ddp address object on this node corresponding
  2460. // to this address. This will get the node lock.
  2461. if (broadcast)
  2462. pDest->ata_Node = pAtalkNode->an_NodeAddr.atn_Node;
  2463. AtalkDdpRefByAddrNode(pPortDesc,
  2464. pDest,
  2465. pAtalkNode,
  2466. &pDdpAddr,
  2467. &error);
  2468. // If we had changed the destination node, change it back.
  2469. if (broadcast)
  2470. pDest->ata_Node = ATALK_BROADCAST_NODE;
  2471. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2472. lockHeld = FALSE;
  2473. if (ATALK_SUCCESS(error))
  2474. {
  2475. // Invoke socket handler on this address object.
  2476. // Use the packet pointer directly!
  2477. AtalkDdpInvokeHandler(pPortDesc,
  2478. pDdpAddr,
  2479. pSrc,
  2480. pDest,
  2481. Protocol,
  2482. pPkt,
  2483. PktLen);
  2484. // Remove the reference on the socket
  2485. AtalkDdpDereferenceDpc(pDdpAddr);
  2486. }
  2487. // Remove the reference on the node
  2488. AtalkNodeDereference(pAtalkNode);
  2489. // If we had to deliver to a specific node, we are done.
  2490. if (fSpecific)
  2491. {
  2492. shouldBeRouted = FALSE;
  2493. break;
  2494. }
  2495. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2496. lockHeld = TRUE;
  2497. }
  2498. }
  2499. if (lockHeld)
  2500. {
  2501. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  2502. }
  2503. *ShouldBeRouted = shouldBeRouted;
  2504. }
  2505. USHORT
  2506. AtalkDdpCheckSumBuffer(
  2507. IN PBYTE Buffer,
  2508. IN USHORT BufLen,
  2509. IN USHORT CurrentCheckSum
  2510. )
  2511. /*++
  2512. Routine Description:
  2513. Calculate the DDP checksum of a byte array
  2514. Arguments:
  2515. Return Value:
  2516. --*/
  2517. {
  2518. USHORT CheckSum = CurrentCheckSum;
  2519. ULONG i;
  2520. // The following algorithm is from Inside AppleTalk, Second Edition
  2521. // page 4-17
  2522. for (i = 0; i < BufLen; i++)
  2523. {
  2524. CheckSum += Buffer[i];
  2525. if (CheckSum & 0x8000) // 16-bit rotate left one bit
  2526. {
  2527. CheckSum <<= 1;
  2528. CheckSum ++;
  2529. }
  2530. else CheckSum <<= 1;
  2531. }
  2532. if (CheckSum == 0)
  2533. CheckSum = 0xFFFF;
  2534. return CheckSum;
  2535. }
  2536. USHORT
  2537. AtalkDdpCheckSumPacket(
  2538. IN PBYTE pHdr,
  2539. IN USHORT HdrLen,
  2540. IN PBYTE pPkt,
  2541. IN USHORT PktLen
  2542. )
  2543. /*++
  2544. Routine Description:
  2545. Arguments:
  2546. Return Value:
  2547. --*/
  2548. {
  2549. USHORT checksum = 0;
  2550. // MAX_LDDP_PKT_SIZE is 600, so we use < instead of <=
  2551. ASSERT(HdrLen + PktLen < MAX_LDDP_PKT_SIZE);
  2552. if ((HdrLen + PktLen) < MAX_LDDP_PKT_SIZE)
  2553. {
  2554. if (HdrLen > 0)
  2555. {
  2556. checksum = AtalkDdpCheckSumBuffer(pHdr, HdrLen, 0);
  2557. }
  2558. if (PktLen > 0)
  2559. {
  2560. checksum = AtalkDdpCheckSumBuffer(pPkt, PktLen, checksum);
  2561. }
  2562. }
  2563. return checksum;
  2564. }
  2565. // Calculate the DDP checksum of the passed in buffer. The buffer is described
  2566. // by the buffer descriptor
  2567. USHORT
  2568. AtalkDdpCheckSumBufferDesc(
  2569. IN PBUFFER_DESC pBuffDesc,
  2570. IN USHORT Offset
  2571. )
  2572. /*++
  2573. Routine Description:
  2574. Arguments:
  2575. Return Value:
  2576. --*/
  2577. {
  2578. PBYTE pBuf;
  2579. USHORT checksum = 0;
  2580. while (pBuffDesc != NULL)
  2581. {
  2582. if (pBuffDesc->bd_Flags & BD_CHAR_BUFFER)
  2583. {
  2584. pBuf = pBuffDesc->bd_CharBuffer;
  2585. }
  2586. else
  2587. {
  2588. pBuf = MmGetSystemAddressForMdlSafe(
  2589. pBuffDesc->bd_OpaqueBuffer,
  2590. NormalPagePriority);
  2591. }
  2592. if (pBuf != NULL) {
  2593. checksum = AtalkDdpCheckSumBuffer(pBuf, pBuffDesc->bd_Length, checksum);
  2594. pBuffDesc = pBuffDesc->bd_Next;
  2595. }
  2596. }
  2597. return checksum;
  2598. }
  2599. // This routine needs to verify that the socket does not already
  2600. // exist on the node. If it doesnt it will alloc the ddp address
  2601. // object and link it into the node and do all the required initialization.
  2602. // The node is guaranteed to be referenced.
  2603. ATALK_ERROR
  2604. atalkDdpAllocSocketOnNode(
  2605. IN PPORT_DESCRIPTOR pPortDesc,
  2606. IN BYTE Socket,
  2607. IN PATALK_NODE pAtalkNode,
  2608. IN DDPAO_HANDLER pSktHandler OPTIONAL,
  2609. IN PVOID pSktCtx OPTIONAL,
  2610. IN BYTE Protocol OPTIONAL,
  2611. IN PATALK_DEV_CTX pDevCtx,
  2612. OUT PDDP_ADDROBJ pDdpAddr
  2613. )
  2614. /*++
  2615. Routine Description:
  2616. Arguments:
  2617. Return Value:
  2618. --*/
  2619. {
  2620. ATALK_ADDR addr;
  2621. PDDP_ADDROBJ pDdpAddrx;
  2622. KIRQL OldIrql;
  2623. int i, j, index;
  2624. BOOLEAN found = TRUE;
  2625. ATALK_ERROR error = ATALK_NO_ERROR;
  2626. // See if the socket exists else, link our new socket into
  2627. // the node linkage. All within a critical section.
  2628. addr.ata_Network = pAtalkNode->an_NodeAddr.atn_Network;
  2629. addr.ata_Node = pAtalkNode->an_NodeAddr.atn_Node;
  2630. addr.ata_Socket = Socket;
  2631. // Now reference the node on which this socket will reside.
  2632. // This will go away when the socket is closed.
  2633. AtalkNodeReferenceByPtr(pAtalkNode, &error);
  2634. if (!ATALK_SUCCESS(error))
  2635. {
  2636. TMPLOGERR();
  2637. return error;
  2638. }
  2639. ACQUIRE_SPIN_LOCK(&pAtalkNode->an_Lock, &OldIrql);
  2640. if (Socket == DYNAMIC_SOCKET)
  2641. {
  2642. // Two attempts if we are at the end of the range and restart from
  2643. // the beginning.
  2644. for (j = 0; (j < NUM_USER_NODES) && found; j++)
  2645. {
  2646. for (i = pAtalkNode->an_NextDynSkt; i <= LAST_DYNAMIC_SOCKET; i++)
  2647. {
  2648. addr.ata_Socket = (BYTE)i;
  2649. index = HASH_ATALK_ADDR(&addr) % NODE_DDPAO_HASH_SIZE;
  2650. found = atalkDdpFindAddrOnList(pAtalkNode, index, (BYTE)i, &pDdpAddrx);
  2651. if (found)
  2652. continue;
  2653. Socket = (BYTE)i;
  2654. break;
  2655. }
  2656. // Now if still havent found the socket id, set NextDynSkt to
  2657. // beginning of the range and try again.
  2658. if (found)
  2659. {
  2660. pAtalkNode->an_NextDynSkt = FIRST_DYNAMIC_SOCKET;
  2661. continue;
  2662. }
  2663. // Not found. Increment next id to be used.
  2664. if (++(pAtalkNode->an_NextDynSkt) == 0)
  2665. {
  2666. // We wrapped! Set the value to the lowest dynamic
  2667. // socket. Thats what it should have been initialized
  2668. // to.
  2669. pAtalkNode->an_NextDynSkt = FIRST_DYNAMIC_SOCKET;
  2670. }
  2671. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  2672. ("atalkDdpAllocSocketOnNode: Created dynamic socket %x\n", Socket));
  2673. // Done.
  2674. break;
  2675. }
  2676. if (found)
  2677. {
  2678. error = ATALK_SOCKET_NODEFULL;
  2679. }
  2680. }
  2681. else
  2682. {
  2683. index = HASH_ATALK_ADDR(&addr) % NODE_DDPAO_HASH_SIZE;
  2684. found = atalkDdpFindAddrOnList(pAtalkNode, index, (BYTE)Socket, &pDdpAddrx);
  2685. if (found)
  2686. {
  2687. error = ATALK_SOCKET_EXISTS;
  2688. }
  2689. }
  2690. if (ATALK_SUCCESS(error))
  2691. {
  2692. // Initialize and thread in the structure
  2693. pDdpAddr->ddpao_Signature = DDPAO_SIGNATURE;
  2694. pDdpAddr->ddpao_RefCount = 1; // Creation
  2695. pDdpAddr->ddpao_DevCtx = pDevCtx;
  2696. pDdpAddr->ddpao_Node = pAtalkNode;
  2697. pDdpAddr->ddpao_Addr.ata_Network = pAtalkNode->an_NodeAddr.atn_Network;
  2698. pDdpAddr->ddpao_Addr.ata_Node = pAtalkNode->an_NodeAddr.atn_Node;
  2699. pDdpAddr->ddpao_Addr.ata_Socket = Socket;
  2700. pDdpAddr->ddpao_Protocol = Protocol;
  2701. pDdpAddr->ddpao_Handler = pSktHandler;
  2702. pDdpAddr->ddpao_HandlerCtx = pSktCtx;
  2703. INITIALIZE_SPIN_LOCK(&pDdpAddr->ddpao_Lock);
  2704. InitializeListHead(&pDdpAddr->ddpao_ReadLinkage);
  2705. // We use 'index' to link this in.
  2706. pDdpAddr->ddpao_Next = pAtalkNode->an_DdpAoHash[index];
  2707. pAtalkNode->an_DdpAoHash[index] = pDdpAddr;
  2708. }
  2709. RELEASE_SPIN_LOCK(&pAtalkNode->an_Lock, OldIrql);
  2710. // If we failed, Dereference the node
  2711. if (!ATALK_SUCCESS(error))
  2712. AtalkNodeDereference(pAtalkNode);
  2713. return error;
  2714. }
  2715. BOOLEAN
  2716. atalkDdpFindAddrOnList(
  2717. IN PATALK_NODE pAtalkNode,
  2718. IN ULONG Index,
  2719. IN BYTE Socket,
  2720. OUT PDDP_ADDROBJ * ppDdpAddr
  2721. )
  2722. /*++
  2723. Routine Description:
  2724. Arguments:
  2725. Return Value:
  2726. --*/
  2727. {
  2728. PDDP_ADDROBJ pDdpAddr;
  2729. BOOLEAN found = FALSE;
  2730. for (pDdpAddr = pAtalkNode->an_DdpAoHash[Index];
  2731. pDdpAddr != NULL;
  2732. pDdpAddr = pDdpAddr->ddpao_Next)
  2733. {
  2734. if (pDdpAddr->ddpao_Addr.ata_Socket == Socket)
  2735. {
  2736. *ppDdpAddr = pDdpAddr;
  2737. found = TRUE;
  2738. break;
  2739. }
  2740. }
  2741. return found;
  2742. }
  2743. VOID
  2744. AtalkDdpRefByAddr(
  2745. IN PPORT_DESCRIPTOR pPortDesc,
  2746. IN PATALK_ADDR pAtalkAddr,
  2747. OUT PDDP_ADDROBJ * ppDdpAddr,
  2748. OUT PATALK_ERROR pErr
  2749. )
  2750. /*++
  2751. Routine Description:
  2752. Arguments:
  2753. Return Value:
  2754. --*/
  2755. {
  2756. ULONG index;
  2757. ATALK_NODEADDR node;
  2758. PATALK_NODE pAtalkNode;
  2759. PDDP_ADDROBJ pDdpAddr;
  2760. KIRQL OldIrql;
  2761. ATALK_ERROR ErrorCode;
  2762. node.atn_Network = pAtalkAddr->ata_Network;
  2763. node.atn_Node = pAtalkAddr->ata_Node;
  2764. // First find the node on this port given its address
  2765. AtalkNodeReferenceByAddr(pPortDesc,
  2766. &node,
  2767. &pAtalkNode,
  2768. &ErrorCode);
  2769. if (ATALK_SUCCESS(ErrorCode))
  2770. {
  2771. ASSERT(VALID_ATALK_NODE(pAtalkNode));
  2772. index = HASH_ATALK_ADDR(pAtalkAddr) % NODE_DDPAO_HASH_SIZE;
  2773. ACQUIRE_SPIN_LOCK(&pAtalkNode->an_Lock, &OldIrql);
  2774. if(atalkDdpFindAddrOnList(pAtalkNode,
  2775. index,
  2776. pAtalkAddr->ata_Socket,
  2777. &pDdpAddr))
  2778. {
  2779. AtalkDdpReferenceByPtr(pDdpAddr, &ErrorCode);
  2780. if (ATALK_SUCCESS(ErrorCode))
  2781. {
  2782. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  2783. *ppDdpAddr = pDdpAddr;
  2784. }
  2785. }
  2786. else
  2787. {
  2788. ErrorCode = ATALK_DDP_NOTFOUND;
  2789. }
  2790. RELEASE_SPIN_LOCK(&pAtalkNode->an_Lock, OldIrql);
  2791. // Remove the node reference
  2792. ASSERT(VALID_ATALK_NODE(pAtalkNode));
  2793. AtalkNodeDereference(pAtalkNode);
  2794. }
  2795. *pErr = ErrorCode;
  2796. }
  2797. VOID
  2798. AtalkDdpRefByAddrNode(
  2799. IN PPORT_DESCRIPTOR pPortDesc,
  2800. IN PATALK_ADDR pAtalkAddr,
  2801. IN PATALK_NODE pAtalkNode,
  2802. OUT PDDP_ADDROBJ * ppDdpAddr,
  2803. OUT PATALK_ERROR pErr
  2804. )
  2805. /*++
  2806. Routine Description:
  2807. Arguments:
  2808. Return Value:
  2809. --*/
  2810. {
  2811. ULONG index;
  2812. KIRQL OldIrql;
  2813. PDDP_ADDROBJ pDdpAddr;
  2814. ASSERT(VALID_ATALK_NODE(pAtalkNode));
  2815. index = HASH_ATALK_ADDR(pAtalkAddr) % NODE_DDPAO_HASH_SIZE;
  2816. ACQUIRE_SPIN_LOCK(&pAtalkNode->an_Lock, &OldIrql);
  2817. if(atalkDdpFindAddrOnList(pAtalkNode,
  2818. index,
  2819. pAtalkAddr->ata_Socket,
  2820. &pDdpAddr))
  2821. {
  2822. AtalkDdpReferenceByPtr(pDdpAddr, pErr);
  2823. if (ATALK_SUCCESS(*pErr))
  2824. {
  2825. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  2826. *ppDdpAddr = pDdpAddr;
  2827. }
  2828. }
  2829. else
  2830. {
  2831. *pErr = ATALK_DDP_NOTFOUND;
  2832. }
  2833. RELEASE_SPIN_LOCK(&pAtalkNode->an_Lock, OldIrql);
  2834. }
  2835. VOID
  2836. AtalkDdpRefNextNc(
  2837. IN PDDP_ADDROBJ pDdpAddr,
  2838. IN PDDP_ADDROBJ * ppDdpAddr,
  2839. OUT PATALK_ERROR pErr
  2840. )
  2841. /*++
  2842. Routine Description:
  2843. MUST BE CALLED WITH THE NODE LOCK HELD!
  2844. Arguments:
  2845. Return Value:
  2846. --*/
  2847. {
  2848. *pErr = ATALK_FAILURE;
  2849. *ppDdpAddr = NULL;
  2850. for (; pDdpAddr != NULL; pDdpAddr = pDdpAddr->ddpao_Next)
  2851. {
  2852. AtalkDdpReferenceByPtrDpc(pDdpAddr, pErr);
  2853. if (ATALK_SUCCESS(*pErr))
  2854. {
  2855. // Ok, this address is referenced!
  2856. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  2857. *ppDdpAddr = pDdpAddr;
  2858. break;
  2859. }
  2860. }
  2861. }
  2862. VOID FASTCALL
  2863. AtalkDdpDeref(
  2864. IN OUT PDDP_ADDROBJ pDdpAddr,
  2865. IN BOOLEAN AtDpc
  2866. )
  2867. /*++
  2868. Routine Description:
  2869. Arguments:
  2870. Return Value:
  2871. --*/
  2872. {
  2873. ATALK_ERROR error = ATALK_NO_ERROR;
  2874. PATALK_NODE pNode = pDdpAddr->ddpao_Node;
  2875. BOOLEAN done = FALSE;
  2876. KIRQL OldIrql;
  2877. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  2878. if (AtDpc)
  2879. {
  2880. ACQUIRE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  2881. }
  2882. else
  2883. {
  2884. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  2885. }
  2886. ASSERT(pDdpAddr->ddpao_RefCount > 0);
  2887. if (--(pDdpAddr->ddpao_RefCount) == 0)
  2888. {
  2889. done = TRUE;
  2890. }
  2891. if (AtDpc)
  2892. {
  2893. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  2894. }
  2895. else
  2896. {
  2897. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  2898. }
  2899. if (done)
  2900. {
  2901. PDDP_ADDROBJ * ppDdpAddr;
  2902. int index;
  2903. //
  2904. // if this is a zombie socket (that is, it was cleaned up but not freed
  2905. // because it's an external socket) then now is the time to free it.
  2906. // Cleanup is all done already.
  2907. //
  2908. if ((pDdpAddr->ddpao_Flags & DDPAO_SOCK_PNPZOMBIE) != 0)
  2909. {
  2910. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  2911. ("AtalkDdpDeref..: zombie addr %lx (%lx) freed\n",
  2912. pDdpAddr,pDdpAddr->ddpao_Handler));
  2913. // Free the address structure
  2914. AtalkFreeMemory(pDdpAddr);
  2915. return;
  2916. }
  2917. ASSERT((pDdpAddr->ddpao_Flags & DDPAO_CLOSING) != 0);
  2918. if ((pDdpAddr->ddpao_Flags & DDPAO_CLOSING) == 0)
  2919. {
  2920. KeBugCheck(0);
  2921. }
  2922. // Remove this guy from the node linkage
  2923. if (AtDpc)
  2924. {
  2925. ACQUIRE_SPIN_LOCK_DPC(&pNode->an_Lock);
  2926. }
  2927. else
  2928. {
  2929. ACQUIRE_SPIN_LOCK(&pNode->an_Lock, &OldIrql);
  2930. }
  2931. index = HASH_ATALK_ADDR(&pDdpAddr->ddpao_Addr) % NODE_DDPAO_HASH_SIZE;
  2932. for (ppDdpAddr = &pNode->an_DdpAoHash[index];
  2933. *ppDdpAddr != NULL;
  2934. ppDdpAddr = &((*ppDdpAddr)->ddpao_Next))
  2935. {
  2936. if (*ppDdpAddr == pDdpAddr)
  2937. {
  2938. *ppDdpAddr = pDdpAddr->ddpao_Next;
  2939. break;
  2940. }
  2941. }
  2942. if (AtDpc)
  2943. {
  2944. RELEASE_SPIN_LOCK_DPC(&pNode->an_Lock);
  2945. }
  2946. else
  2947. {
  2948. RELEASE_SPIN_LOCK(&pNode->an_Lock, OldIrql);
  2949. }
  2950. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  2951. ("AtalkDdpDeref: Closing ddp socket %lx\n", pDdpAddr->ddpao_Addr.ata_Socket));
  2952. if (pDdpAddr->ddpao_EventInfo != NULL)
  2953. {
  2954. AtalkFreeMemory(pDdpAddr->ddpao_EventInfo);
  2955. }
  2956. // Call the completion routines
  2957. if (*pDdpAddr->ddpao_CloseComp != NULL)
  2958. {
  2959. (*pDdpAddr->ddpao_CloseComp)(ATALK_NO_ERROR, pDdpAddr->ddpao_CloseCtx);
  2960. }
  2961. // Free the address structure
  2962. AtalkFreeMemory(pDdpAddr);
  2963. // Dereference the node for this address
  2964. AtalkNodeDereference(pNode);
  2965. }
  2966. }
  2967. VOID
  2968. AtalkDdpNewHandlerForSocket(
  2969. IN PDDP_ADDROBJ pDdpAddr,
  2970. IN DDPAO_HANDLER pSktHandler,
  2971. IN PVOID pSktHandlerCtx
  2972. )
  2973. /*++
  2974. Routine Description:
  2975. Arguments:
  2976. Return Value:
  2977. --*/
  2978. {
  2979. KIRQL OldIrql;
  2980. ASSERT (VALID_DDP_ADDROBJ(pDdpAddr));
  2981. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  2982. pDdpAddr->ddpao_Handler = pSktHandler;
  2983. pDdpAddr->ddpao_HandlerCtx = pSktHandlerCtx;
  2984. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  2985. }