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

2220 lines
57 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. aarp.c
  5. Abstract:
  6. This module contains the Appletalk Address Resolution Protocol code.
  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 the file number for this module for errorlogging.
  17. #define FILENUM AARP
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGEINIT, AtalkInitAarpForNodeOnPort)
  20. #pragma alloc_text(PAGEINIT, AtalkInitAarpForNodeInRange)
  21. #pragma alloc_text(PAGEINIT, atalkInitAarpForNode)
  22. #endif
  23. VOID
  24. AtalkAarpPacketIn(
  25. IN OUT PPORT_DESCRIPTOR pPortDesc,
  26. IN PBYTE pLinkHdr,
  27. IN PBYTE pPkt, // Only aarp data
  28. IN USHORT Length
  29. )
  30. /*++
  31. Routine Description:
  32. Arguments:
  33. Return Value:
  34. --*/
  35. {
  36. PBYTE srcAddr;
  37. PBYTE startOfPkt;
  38. ATALK_NODEADDR srcNode, dstNode;
  39. PBYTE pRouteInfo = NULL;
  40. USHORT routeInfoLen = 0;
  41. ULONG logEventPlace = 0;
  42. USHORT hardwareLen, protocolLength, aarpCommand;
  43. PBUFFER_DESC pBuffDesc;
  44. ATALK_ERROR error;
  45. PVOID pRasConn;
  46. PATCPCONN pAtcpConn=NULL;
  47. PARAPCONN pArapConn=NULL;
  48. DWORD dwFlags;
  49. BOOLEAN fDialInNode=TRUE;
  50. BOOLEAN fThisIsPPP;
  51. TIME TimeS, TimeE, TimeD;
  52. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  53. TimeS = KeQueryPerformanceCounter(NULL);
  54. if (PORT_CLOSING(pPortDesc))
  55. {
  56. // If we are not active, return!
  57. return;
  58. }
  59. if (pPortDesc->pd_NdisPortType == NdisMedium802_5)
  60. {
  61. if (pLinkHdr[TLAP_SRC_OFFSET] & TLAP_SRC_ROUTING_MASK)
  62. {
  63. routeInfoLen = (pLinkHdr[TLAP_ROUTE_INFO_OFFSET] & TLAP_ROUTE_INFO_SIZE_MASK);
  64. // First, glean any AARP information that we can, then handle the DDP
  65. // packet. This guy also makes sure we have a good 802.2 header...
  66. //
  67. // Need to make a localcopy of the source address and then turn
  68. // the source routing bit off before calling AarpGleanInfo
  69. //
  70. // (HdrBuf)[TLAP_SRC_OFFSET] = ((HdrBuf)[TLAP_SRC_OFFSET] & ~TLAP_SRC_ROUTING_MASK);
  71. pLinkHdr[TLAP_SRC_OFFSET] &= ~TLAP_SRC_ROUTING_MASK;
  72. pRouteInfo = pLinkHdr + TLAP_ROUTE_INFO_OFFSET;
  73. }
  74. }
  75. startOfPkt = pPkt;
  76. ASSERT(routeInfoLen <= TLAP_MAX_ROUTING_BYTES);
  77. // Pull out the information we'll be playing with. All three valid AARP
  78. // commands use the same packet format. But have some variable length
  79. // fields.
  80. // The packet will not include the 802.2 header!
  81. // pPkt += IEEE8022_HDR_LEN;
  82. // Length -= IEEE8022_HDR_LEN;
  83. pPkt += AARP_HW_LEN_OFFSET; // Skip the hardware type
  84. do
  85. {
  86. GETBYTE2SHORT (&hardwareLen, pPkt);
  87. pPkt++ ;
  88. if ((hardwareLen < AARP_MIN_HW_ADDR_LEN ) ||
  89. (hardwareLen > AARP_MAX_HW_ADDR_LEN))
  90. {
  91. logEventPlace = (FILENUM | __LINE__);
  92. break;
  93. }
  94. GETBYTE2SHORT(&protocolLength, pPkt);
  95. pPkt ++;
  96. if (protocolLength != AARP_PROTO_ADDR_LEN)
  97. {
  98. logEventPlace = (FILENUM | __LINE__);
  99. break;
  100. }
  101. GETSHORT2SHORT(&aarpCommand, pPkt);
  102. pPkt += 2;
  103. // Remember where the source address is in the packet for
  104. // entering it into the mapping table
  105. srcAddr = pPkt;
  106. // Skip over the source hardware length
  107. // Skip over to leading null pad on logical address.
  108. pPkt += (hardwareLen + 1);
  109. GETSHORT2SHORT(&srcNode.atn_Network, pPkt);
  110. pPkt += 2;
  111. srcNode.atn_Node = *pPkt++;
  112. // Skip the destination hardware address
  113. // Skip over to leading null pad on logical destination address.
  114. pPkt += (hardwareLen + 1);
  115. GETSHORT2SHORT(&dstNode.atn_Network, pPkt);
  116. pPkt += 2;
  117. dstNode.atn_Node = *pPkt++;
  118. // We should have eaten the whole packet...
  119. if ((ULONG)(pPkt - startOfPkt) != Length)
  120. {
  121. logEventPlace = (FILENUM | __LINE__);
  122. break;
  123. }
  124. // Ignore any AARPs from us.
  125. ASSERT(hardwareLen == TLAP_ADDR_LEN);
  126. if (AtalkFixedCompareCaseSensitive(srcAddr,
  127. hardwareLen,
  128. pPortDesc->pd_PortAddr,
  129. hardwareLen))
  130. {
  131. break;
  132. }
  133. // Handle the Aarp command packets
  134. switch(aarpCommand)
  135. {
  136. case AARP_REQUEST:
  137. // We can get valid mapping info from a request, use it!
  138. // We are guaranteed routing info is positive and is not odd
  139. // (atleast 2 bytes).
  140. ASSERT((routeInfoLen >= 0) && (routeInfoLen != 1));
  141. if (routeInfoLen > 0)
  142. atalkAarpTuneRouteInfo(pPortDesc, pRouteInfo);
  143. atalkAarpEnterIntoAmt(pPortDesc,
  144. &srcNode,
  145. srcAddr,
  146. hardwareLen,
  147. pRouteInfo,
  148. routeInfoLen);
  149. // After that, we can ignore any request not destined for us.
  150. if (!AtalkNodeExistsOnPort(pPortDesc, &dstNode))
  151. {
  152. // our dial-in clients can only be in the network range of the
  153. // default port. If another adapter is plugged into the same net
  154. // as the default adapter, we don't want dial-in clients to
  155. // mess things up: ignore anything not coming on default adapter
  156. // (as far as dial-in clients go)
  157. if (pPortDesc != AtalkDefaultPort)
  158. {
  159. break;
  160. }
  161. //
  162. // is this one of our dial-in "nodes"? If so, we must send out
  163. // a proxy response from our DefaultPort.
  164. //
  165. if ((pRasConn = FindAndRefRasConnByAddr(dstNode,
  166. &dwFlags,
  167. &fThisIsPPP)) != NULL)
  168. {
  169. if (fThisIsPPP)
  170. {
  171. ASSERT(((PATCPCONN)pRasConn)->Signature == ATCPCONN_SIGNATURE);
  172. DerefPPPConn((PATCPCONN)pRasConn);
  173. }
  174. else
  175. {
  176. ASSERT(((PARAPCONN)pRasConn)->Signature == ARAPCONN_SIGNATURE);
  177. DerefArapConn((PARAPCONN)pRasConn);
  178. }
  179. }
  180. //
  181. // nope, a dial-in client with such a node addr doesn't exist either..
  182. //
  183. else
  184. {
  185. break;
  186. }
  187. }
  188. // The're asking about us, speak the truth.
  189. pBuffDesc = BUILD_AARPRESPONSE(pPortDesc,
  190. hardwareLen,
  191. srcAddr,
  192. pRouteInfo,
  193. routeInfoLen,
  194. dstNode,
  195. srcNode);
  196. if (pBuffDesc == NULL)
  197. {
  198. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  199. ("AtalkAarpPacketIn: Mem alloc failed %d\n", __LINE__));
  200. break;
  201. }
  202. if (!ATALK_SUCCESS(AtalkNdisSendPacket(pPortDesc,
  203. pBuffDesc,
  204. AtalkAarpSendComplete,
  205. NULL)))
  206. {
  207. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  208. ("AtalkAarpPacketIn: SendPkt %lx failed %d\n",
  209. pBuffDesc->bd_CharBuffer, __LINE__));
  210. LOG_ERRORONPORT(pPortDesc,
  211. EVENT_ATALK_AARP_SEND_FAIL,
  212. STATUS_INSUFFICIENT_RESOURCES,
  213. pBuffDesc->bd_CharBuffer,
  214. Length);
  215. // We allocated the packet.
  216. AtalkAarpSendComplete(NDIS_STATUS_FAILURE,
  217. pBuffDesc,
  218. NULL);
  219. }
  220. break;
  221. case AARP_RESPONSE:
  222. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  223. if (pPortDesc->pd_Flags & PD_FINDING_NODE)
  224. {
  225. // No doubt, this is a response to our probe, check to make sure
  226. // the address matches, if so set the "used" flag.
  227. if (ATALK_NODES_EQUAL(&dstNode, &pPortDesc->pd_TentativeNodeAddr))
  228. {
  229. pPortDesc->pd_Flags |= PD_NODE_IN_USE;
  230. // Wakeup the blocking thread...
  231. KeSetEvent(&pPortDesc->pd_NodeAcquireEvent, IO_NETWORK_INCREMENT, FALSE);
  232. }
  233. }
  234. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  235. // is this one of our dial-in "nodes"? If so, check if we are probing
  236. if ((pRasConn = FindAndRefRasConnByAddr(dstNode,
  237. &dwFlags,
  238. &fThisIsPPP)) != NULL)
  239. {
  240. //
  241. // our dial-in clients can only be in the network range of the
  242. // default port
  243. //
  244. ASSERT(pPortDesc == AtalkDefaultPort);
  245. pAtcpConn = NULL;
  246. pArapConn = NULL;
  247. if (fThisIsPPP)
  248. {
  249. pAtcpConn = (PATCPCONN)pRasConn;
  250. ASSERT(pAtcpConn->Signature == ATCPCONN_SIGNATURE);
  251. }
  252. else
  253. {
  254. pArapConn = (PARAPCONN)pRasConn;
  255. ASSERT(pArapConn->Signature == ARAPCONN_SIGNATURE);
  256. }
  257. // PPP client?
  258. if (pAtcpConn)
  259. {
  260. if (dwFlags & ATCP_FINDING_NODE)
  261. {
  262. ACQUIRE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  263. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  264. ("AtalkAarpPacketIn: PPP: someone owns %lx %x, retrying\n",
  265. dstNode.atn_Network,dstNode.atn_Node));
  266. pAtcpConn->Flags |= ATCP_NODE_IN_USE;
  267. // Wakeup the blocking thread...
  268. KeSetEvent(&pAtcpConn->NodeAcquireEvent,
  269. IO_NETWORK_INCREMENT,
  270. FALSE);
  271. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  272. }
  273. // remove refcount put by FindAndRefRasConnByAddr
  274. DerefPPPConn(pAtcpConn);
  275. }
  276. // nope, ARAP client
  277. else
  278. {
  279. if (dwFlags & ARAP_FINDING_NODE)
  280. {
  281. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  282. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  283. ("AtalkAarpPacketIn: ARAP: someone owns %lx %x, retrying\n",
  284. dstNode.atn_Network,dstNode.atn_Node));
  285. pArapConn->Flags |= ARAP_NODE_IN_USE;
  286. // Wakeup the blocking thread...
  287. KeSetEvent(&pArapConn->NodeAcquireEvent,
  288. IO_NETWORK_INCREMENT,
  289. FALSE);
  290. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  291. }
  292. // remove refcount put by FindAndRefRasConnByAddr
  293. DerefArapConn(pArapConn);
  294. }
  295. }
  296. // This must have been a response to a probe or request... update our
  297. // mapping table.
  298. if (routeInfoLen != 0)
  299. {
  300. atalkAarpTuneRouteInfo(pPortDesc, pRouteInfo);
  301. }
  302. atalkAarpEnterIntoAmt(pPortDesc,
  303. &srcNode,
  304. srcAddr,
  305. hardwareLen,
  306. pRouteInfo,
  307. routeInfoLen);
  308. break;
  309. case AARP_PROBE:
  310. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  311. if (pPortDesc->pd_Flags & PD_FINDING_NODE)
  312. {
  313. // If we get a probe for our current tentative address, set the
  314. // "used" flag.
  315. if (ATALK_NODES_EQUAL(&dstNode, &pPortDesc->pd_TentativeNodeAddr))
  316. {
  317. pPortDesc->pd_Flags |= PD_NODE_IN_USE;
  318. KeSetEvent(&pPortDesc->pd_NodeAcquireEvent,
  319. IO_NETWORK_INCREMENT,
  320. FALSE);
  321. }
  322. }
  323. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  324. if (pPortDesc != AtalkDefaultPort)
  325. {
  326. break;
  327. }
  328. fDialInNode = FALSE;
  329. // is the probe asking about one of our dial-in nodes? if so, we
  330. // must defend that address (or, if we are trying to acquire this
  331. // node addr, stop that since someone else is doing the same)
  332. //
  333. // our dial-in clients can only be in the network range of the
  334. // default port. If another adapter is plugged into the same net
  335. // as the default adapter, we don't want dial-in clients to
  336. // mess things up: ignore anything not coming on default adapter
  337. // (as far as dial-in clients go)
  338. if ((pPortDesc == AtalkDefaultPort) &&
  339. ((pRasConn = FindAndRefRasConnByAddr(dstNode,
  340. &dwFlags,
  341. &fThisIsPPP)) != NULL))
  342. {
  343. pAtcpConn = NULL;
  344. pArapConn = NULL;
  345. if (fThisIsPPP)
  346. {
  347. pAtcpConn = (PATCPCONN)pRasConn;
  348. ASSERT(pAtcpConn->Signature == ATCPCONN_SIGNATURE);
  349. }
  350. else
  351. {
  352. pArapConn = (PARAPCONN)pRasConn;
  353. ASSERT(pArapConn->Signature == ARAPCONN_SIGNATURE);
  354. }
  355. // PPP client?
  356. if (pAtcpConn)
  357. {
  358. if (dwFlags & ATCP_FINDING_NODE)
  359. {
  360. ACQUIRE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  361. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  362. ("AtalkAarpPacketIn: PPP: someone trying to acquire %lx %x, retrying\n",
  363. dstNode.atn_Network,dstNode.atn_Node));
  364. pAtcpConn->Flags |= ATCP_NODE_IN_USE;
  365. // Wakeup the blocking thread...
  366. KeSetEvent(&pAtcpConn->NodeAcquireEvent,
  367. IO_NETWORK_INCREMENT,
  368. FALSE);
  369. RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
  370. }
  371. else
  372. {
  373. fDialInNode = TRUE;
  374. }
  375. // remove refcount put by FindAndRefRasConnByAddr
  376. DerefPPPConn(pAtcpConn);
  377. }
  378. // nope, ARAP client
  379. else
  380. {
  381. if (dwFlags & ARAP_FINDING_NODE)
  382. {
  383. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  384. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN,
  385. ("AtalkAarpPacketIn: ARAP: someone trying to acquire %lx %x, retrying\n",
  386. dstNode.atn_Network,dstNode.atn_Node));
  387. pArapConn->Flags |= ARAP_NODE_IN_USE;
  388. // Wakeup the blocking thread...
  389. KeSetEvent(&pArapConn->NodeAcquireEvent,
  390. IO_NETWORK_INCREMENT,
  391. FALSE);
  392. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  393. }
  394. else
  395. {
  396. fDialInNode = TRUE;
  397. }
  398. // remove refcount put by FindAndRefRasConnByAddr
  399. DerefArapConn(pArapConn);
  400. }
  401. }
  402. // If the probe isn't asking about one of our AppleTalk addresses,
  403. // and it's not one of our dial-in nodes either, drop it on the floor.
  404. if (!fDialInNode && !AtalkNodeExistsOnPort(pPortDesc, &dstNode))
  405. {
  406. break;
  407. }
  408. // The're talking to us! Build and send the response.
  409. if (routeInfoLen != 0)
  410. {
  411. atalkAarpTuneRouteInfo(pPortDesc, pRouteInfo);
  412. }
  413. if (fDialInNode)
  414. {
  415. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  416. ("AtalkAarpPacketIn: defending dial-in client's addr %x %x\n",
  417. dstNode.atn_Network,dstNode.atn_Node));
  418. }
  419. pBuffDesc = BUILD_AARPRESPONSE(pPortDesc,
  420. hardwareLen,
  421. srcAddr,
  422. pRouteInfo,
  423. routeInfoLen,
  424. dstNode,
  425. srcNode);
  426. if (pBuffDesc == NULL)
  427. {
  428. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  429. ("AtalkAarpPacketIn: Mem alloc failed %d\n", __LINE__));
  430. break;
  431. }
  432. if (!ATALK_SUCCESS(AtalkNdisSendPacket(pPortDesc,
  433. pBuffDesc,
  434. AtalkAarpSendComplete,
  435. NULL)))
  436. {
  437. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  438. ("AtalkAarpPacketIn: SendPkt %lx failed %d\n",
  439. pBuffDesc->bd_CharBuffer, __LINE__));
  440. LOG_ERRORONPORT(pPortDesc,
  441. EVENT_ATALK_AARP_SEND_FAIL,
  442. STATUS_INSUFFICIENT_RESOURCES,
  443. pBuffDesc->bd_CharBuffer,
  444. Length);
  445. // We allocated the packet. This will free it up.
  446. AtalkAarpSendComplete(NDIS_STATUS_FAILURE,
  447. pBuffDesc,
  448. NULL);
  449. }
  450. break;
  451. default:
  452. logEventPlace = (FILENUM | __LINE__);
  453. break;
  454. }
  455. } while (FALSE);
  456. if (logEventPlace)
  457. {
  458. LOG_ERRORONPORT(pPortDesc,
  459. EVENT_ATALK_INVALIDAARPPACKET,
  460. logEventPlace,
  461. startOfPkt,
  462. Length);
  463. }
  464. TimeE = KeQueryPerformanceCounter(NULL);
  465. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  466. INTERLOCKED_ADD_LARGE_INTGR_DPC(
  467. &pPortDesc->pd_PortStats.prtst_AarpPacketInProcessTime,
  468. TimeD,
  469. &AtalkStatsLock.SpinLock);
  470. INTERLOCKED_INCREMENT_LONG_DPC(
  471. &pPortDesc->pd_PortStats.prtst_NumAarpPacketsIn,
  472. &AtalkStatsLock.SpinLock);
  473. }
  474. VOID
  475. AtalkAarpSendComplete(
  476. NDIS_STATUS Status,
  477. PBUFFER_DESC pBuffDesc,
  478. PSEND_COMPL_INFO pSendInfo
  479. )
  480. /*++
  481. Routine Description:
  482. Arguments:
  483. Return Value:
  484. --*/
  485. {
  486. ASSERT(pBuffDesc->bd_Next == NULL);
  487. ASSERT(pBuffDesc->bd_Flags & BD_CHAR_BUFFER);
  488. AtalkNdisFreeBuf(pBuffDesc);
  489. }
  490. #define AtalkAarpUpdateBre(_pPortDesc, \
  491. _Network, \
  492. _SrcAddr, \
  493. _AddrLen, \
  494. _RouteInfo, \
  495. _RouteInfoLen) \
  496. { \
  497. PBRE pBre, *ppBre; \
  498. int index; \
  499. BLKID BlkId; \
  500. \
  501. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO, \
  502. ("AtalkAarpUpdateBre: Entering %x in brc\n", _Network)); \
  503. \
  504. index = (int)((_Network) & (PORT_BRC_HASH_SIZE - 1)); \
  505. \
  506. ACQUIRE_SPIN_LOCK_DPC(&(_pPortDesc)->pd_Lock); \
  507. \
  508. for (ppBre = &(_pPortDesc)->pd_Brc[index]; \
  509. (pBre = *ppBre) != NULL; \
  510. ppBre = &pBre->bre_Next) \
  511. { \
  512. if (pBre->bre_Network == (_Network)) \
  513. { \
  514. /* \
  515. * Unlink it from the list since it could potentially \
  516. * be freed if the routeinfolen grew and also we want \
  517. * to link it again at the head of the list \
  518. */ \
  519. *ppBre = pBre->bre_Next; \
  520. break; \
  521. } \
  522. } \
  523. \
  524. if ((pBre != NULL) && \
  525. (pBre->bre_RouteInfoLen < (BYTE)(_RouteInfoLen))) \
  526. { \
  527. AtalkBPFreeBlock(pBre); \
  528. pBre = NULL; \
  529. } \
  530. \
  531. if (pBre == NULL) \
  532. { \
  533. BlkId = BLKID_BRE; \
  534. if ((_RouteInfoLen) != 0) \
  535. BlkId = BLKID_BRE_ROUTE; \
  536. pBre = (PBRE)AtalkBPAllocBlock(BlkId); \
  537. } \
  538. \
  539. if (pBre != NULL) \
  540. { \
  541. pBre->bre_Age = 0; \
  542. pBre->bre_Network = (_Network); \
  543. \
  544. COPY_NETWORK_ADDR(pBre->bre_RouterAddr, \
  545. _SrcAddr); \
  546. \
  547. pBre->bre_RouteInfoLen =(BYTE)(_RouteInfoLen); \
  548. \
  549. if ((_RouteInfoLen) > 0) \
  550. RtlCopyMemory((PBYTE)pBre + sizeof(BRE), \
  551. _RouteInfo, \
  552. _RouteInfoLen); \
  553. \
  554. pBre->bre_Next = *ppBre; \
  555. *ppBre = pBre; \
  556. } \
  557. \
  558. RELEASE_SPIN_LOCK_DPC(&(_pPortDesc)->pd_Lock); \
  559. }
  560. BOOLEAN
  561. AtalkAarpGleanInfo(
  562. IN OUT PPORT_DESCRIPTOR pPortDesc,
  563. IN PBYTE SrcAddr,
  564. IN SHORT AddrLen,
  565. IN OUT PBYTE RouteInfo,
  566. IN USHORT RouteInfoLen,
  567. IN PBYTE pPkt,
  568. IN USHORT Length
  569. )
  570. /*++
  571. Routine Description:
  572. Arguments:
  573. Return Value:
  574. --*/
  575. {
  576. ATALK_NODEADDR srcNode, dstNode;
  577. PBYTE startOfPkt;
  578. ULONG logEventPlace = 0;
  579. BYTE offCableInfo;
  580. BOOLEAN result = TRUE;
  581. if (PORT_CLOSING(pPortDesc))
  582. {
  583. // If we are not active, return!
  584. return FALSE;
  585. }
  586. // Packet will not include the 802.2 header!
  587. // pPkt += IEEE8022_HDR_LEN;
  588. // Length -= IEEE8022_HDR_LEN;
  589. // Remember the start of the packet
  590. startOfPkt = pPkt;
  591. // Get the off cable information
  592. offCableInfo = *pPkt;
  593. // Skip the datagram length and checksum fields
  594. pPkt += (2 + 2);
  595. // Get the destination network number
  596. GETSHORT2SHORT(&dstNode.atn_Network, pPkt);
  597. pPkt += sizeof(USHORT);
  598. // Get the source network number
  599. GETSHORT2SHORT(&srcNode.atn_Network, pPkt);
  600. pPkt += sizeof(USHORT);
  601. // Get the destination node id
  602. dstNode.atn_Node = *pPkt++;
  603. // Get the source node id
  604. srcNode.atn_Node = *pPkt++;
  605. do
  606. {
  607. // Do a little verification.
  608. if ((srcNode.atn_Node < MIN_USABLE_ATALKNODE) ||
  609. (srcNode.atn_Node > MAX_USABLE_ATALKNODE) ||
  610. (srcNode.atn_Network < FIRST_VALID_NETWORK) ||
  611. (srcNode.atn_Network > LAST_VALID_NETWORK))
  612. {
  613. // Only bother logging this if we are in some routing capacity,
  614. // otherwise, let A-ROUTER worry about it
  615. if (AtalkRouter)
  616. {
  617. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  618. ("AtalkAarpGleanInfo: dstNode invalid %x.%x\n",
  619. srcNode.atn_Network, srcNode.atn_Node));
  620. logEventPlace = FILENUM | __LINE__;
  621. }
  622. break;
  623. }
  624. if (dstNode.atn_Network > LAST_VALID_NETWORK)
  625. {
  626. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  627. ("AtalkAarpGleanInfo: srcNode invalid %x.%x\n",
  628. dstNode.atn_Network, dstNode.atn_Node));
  629. logEventPlace = FILENUM | __LINE__;
  630. break;
  631. }
  632. // Did the packet come from off this cable? Look at the hop count. If so,
  633. // enter it into our best-router cache.
  634. //
  635. // **NOTE** We assume that the RouteInfo buffer can be written to!
  636. if (RouteInfoLen > 0)
  637. atalkAarpTuneRouteInfo(pPortDesc, RouteInfo);
  638. if ((offCableInfo >> 2) & AARP_OFFCABLE_MASK)
  639. {
  640. AtalkAarpUpdateBre(pPortDesc,
  641. srcNode.atn_Network,
  642. SrcAddr,
  643. AddrLen,
  644. RouteInfo,
  645. RouteInfoLen);
  646. }
  647. else
  648. {
  649. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO,
  650. ("AtalkAarpGleanInfo: Entering %x.%x info in Amt tables\n",
  651. srcNode.atn_Network, srcNode.atn_Node));
  652. // "Glean" AARP information from on-cable packets.
  653. atalkAarpEnterIntoAmt(pPortDesc,
  654. &srcNode,
  655. SrcAddr,
  656. AddrLen,
  657. RouteInfo,
  658. RouteInfoLen);
  659. }
  660. } while (FALSE);
  661. if (logEventPlace)
  662. {
  663. LOG_ERRORONPORT(pPortDesc,
  664. EVENT_ATALK_INVALIDAARPPACKET,
  665. logEventPlace,
  666. startOfPkt,
  667. Length);
  668. }
  669. return (logEventPlace == 0);
  670. }
  671. VOID
  672. AtalkAarpOptGleanInfo(
  673. IN OUT PPORT_DESCRIPTOR pPortDesc,
  674. IN PBYTE pLinkHdr,
  675. IN PATALK_ADDR pSrcAddr,
  676. IN PATALK_ADDR pDestAddr,
  677. IN BOOLEAN OffCablePkt
  678. )
  679. /*++
  680. Routine Description:
  681. Arguments:
  682. Return Value:
  683. --*/
  684. {
  685. ATALK_NODEADDR srcNode, dstNode;
  686. int index;
  687. PBYTE pRouteInfo;
  688. USHORT routeLen = 0, srcOffset;
  689. if (PORT_CLOSING(pPortDesc))
  690. {
  691. // If we are not active, return!
  692. return;
  693. }
  694. switch (pPortDesc->pd_NdisPortType)
  695. {
  696. case NdisMedium802_5:
  697. if (pLinkHdr[TLAP_SRC_OFFSET] & TLAP_SRC_ROUTING_MASK)
  698. {
  699. routeLen = (pLinkHdr[TLAP_ROUTE_INFO_OFFSET] & TLAP_ROUTE_INFO_SIZE_MASK);
  700. //
  701. // First, glean any AARP information that we can, then handle the DDP
  702. // packet. This guy also makes sure we have a good 802.2 header...
  703. //
  704. // Need to make a localcopy of the source address and then turn
  705. // the source routing bit off before calling AarpGleanInfo
  706. //
  707. // (HdrBuf)[TLAP_SRC_OFFSET] = ((HdrBuf)[TLAP_SRC_OFFSET] & ~TLAP_SRC_ROUTING_MASK);
  708. //
  709. pLinkHdr[TLAP_SRC_OFFSET] &= ~TLAP_SRC_ROUTING_MASK;
  710. pRouteInfo = pLinkHdr + TLAP_ROUTE_INFO_OFFSET;
  711. }
  712. srcOffset = TLAP_SRC_OFFSET;
  713. break;
  714. case NdisMedium802_3:
  715. srcOffset = ELAP_SRC_OFFSET;
  716. break;
  717. case NdisMediumFddi:
  718. srcOffset = FDDI_SRC_OFFSET;
  719. break;
  720. default:
  721. KeBugCheck(0);
  722. break;
  723. }
  724. // Get the destination network number
  725. dstNode.atn_Network = pDestAddr->ata_Network;
  726. dstNode.atn_Node = pDestAddr->ata_Node;
  727. srcNode.atn_Network = pSrcAddr->ata_Network;
  728. srcNode.atn_Node = pSrcAddr->ata_Node;
  729. do
  730. {
  731. // Do a little verification.
  732. if ((srcNode.atn_Node < MIN_USABLE_ATALKNODE) ||
  733. (srcNode.atn_Node > MAX_USABLE_ATALKNODE) ||
  734. (srcNode.atn_Network < FIRST_VALID_NETWORK) ||
  735. (srcNode.atn_Network > LAST_VALID_NETWORK))
  736. {
  737. break;
  738. }
  739. if (dstNode.atn_Network > LAST_VALID_NETWORK)
  740. {
  741. break;
  742. }
  743. // Did the packet come from off this cable? Look at the hop count. If so,
  744. // enter it into our best-router cache.
  745. //
  746. // **NOTE** We assume that the pRouteInfo buffer can be written to!
  747. if (routeLen > 0)
  748. atalkAarpTuneRouteInfo(pPortDesc, pRouteInfo);
  749. if (OffCablePkt)
  750. {
  751. AtalkAarpUpdateBre(pPortDesc,
  752. srcNode.atn_Network,
  753. pLinkHdr + srcOffset,
  754. ELAP_ADDR_LEN,
  755. pRouteInfo,
  756. routeLen);
  757. }
  758. else
  759. {
  760. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO,
  761. ("AtalkAarpGleanInfo: Entering %x.%x info in Amt tables\n",
  762. srcNode.atn_Network, srcNode.atn_Node));
  763. // "Glean" AARP information from on-cable packets.
  764. atalkAarpEnterIntoAmt(pPortDesc,
  765. &srcNode,
  766. pLinkHdr + srcOffset,
  767. ELAP_ADDR_LEN,
  768. pRouteInfo,
  769. routeLen);
  770. }
  771. } while (FALSE);
  772. }
  773. ATALK_ERROR
  774. AtalkInitAarpForNodeOnPort(
  775. IN PPORT_DESCRIPTOR pPortDesc,
  776. IN BOOLEAN AllowStartupRange,
  777. IN ATALK_NODEADDR DesiredNode,
  778. IN OUT PATALK_NODE * ppAtalkNode
  779. )
  780. /*++
  781. Routine Description:
  782. Arguments:
  783. Return Value:
  784. --*/
  785. {
  786. ATALK_ERROR error;
  787. PDDP_ADDROBJ pDdpAddr;
  788. ATALK_NODEADDR newNode;
  789. PATALK_NODE pAtalkNode;
  790. KIRQL OldIrql;
  791. BOOLEAN foundNode = FALSE;
  792. BOOLEAN inStartupRange = FALSE, result = TRUE;
  793. if (!ATALK_SUCCESS(AtalkInitNodeAllocate(pPortDesc, &pAtalkNode)))
  794. {
  795. return ATALK_RESR_MEM;
  796. }
  797. // Try to find a new extended Node on the given port; first try for the
  798. // requested address (if specified), else try in this port's cable range
  799. // (if it's known) or in the default cable range (if any), then try the
  800. // start-up range (if allowed).
  801. do
  802. {
  803. if (DesiredNode.atn_Network != UNKNOWN_NETWORK)
  804. {
  805. if (((pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY) == 0) ||
  806. (WITHIN_NETWORK_RANGE(DesiredNode.atn_Network, &pPortDesc->pd_NetworkRange)))
  807. {
  808. foundNode = atalkInitAarpForNode(pPortDesc,
  809. NULL, // not a dial-in client
  810. FALSE, // don't care
  811. DesiredNode.atn_Network,
  812. DesiredNode.atn_Node);
  813. }
  814. // leave if we found a node.
  815. if (foundNode)
  816. {
  817. newNode = DesiredNode;
  818. break;
  819. }
  820. }
  821. if (pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  822. {
  823. foundNode = AtalkInitAarpForNodeInRange(pPortDesc,
  824. NULL, // not a dial-in client
  825. FALSE, // don't care
  826. pPortDesc->pd_NetworkRange,
  827. &newNode);
  828. // leave if we found a node.
  829. if (foundNode)
  830. {
  831. break;
  832. }
  833. }
  834. if (pPortDesc->pd_InitialNetworkRange.anr_FirstNetwork != UNKNOWN_NETWORK)
  835. {
  836. foundNode = AtalkInitAarpForNodeInRange(pPortDesc,
  837. NULL, // not a dial-in client
  838. FALSE, // don't care
  839. pPortDesc->pd_InitialNetworkRange,
  840. &newNode);
  841. // leave if we found a node.
  842. if (foundNode)
  843. {
  844. break;
  845. }
  846. }
  847. // If no place else to try, try the start-up range. Do this even if
  848. // we don't want to end up there.
  849. //
  850. // The idea is that this happens only when we are starting the router
  851. // on one of our ports. So we do not want the router started in the
  852. // startup range. If we do start in the startup range, and we see later
  853. // that we did not see a router in the process,
  854. // we will release the node. Of course, if we are a seed router, we will
  855. // never be here, as the if statement above will be true.
  856. //
  857. inStartupRange = TRUE;
  858. foundNode = AtalkInitAarpForNodeInRange(pPortDesc,
  859. NULL, // not a dial-in client
  860. FALSE, // don't care
  861. AtalkStartupNetworkRange,
  862. &newNode);
  863. break;
  864. } while (FALSE);
  865. // If we have a tentative Node, go on.
  866. if (foundNode)
  867. {
  868. do
  869. {
  870. // Use the allocated structure to set the info.
  871. // Thread this into the port structure.
  872. pAtalkNode->an_NodeAddr = newNode;
  873. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  874. // Reference the port for this node.
  875. AtalkPortRefByPtrNonInterlock(pPortDesc, &error);
  876. if (!ATALK_SUCCESS(error))
  877. {
  878. result = FALSE;
  879. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  880. AtalkFreeMemory(pAtalkNode);
  881. break;
  882. }
  883. // Now put it in the port descriptor
  884. pAtalkNode->an_Next = pPortDesc->pd_Nodes;
  885. pPortDesc->pd_Nodes = pAtalkNode;
  886. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  887. // See who's out there. We need to open the ZIP socket in order to be
  888. // able to hear replies.
  889. if (!ATALK_SUCCESS(AtalkDdpOpenAddress(pPortDesc,
  890. ZONESINFORMATION_SOCKET,
  891. &newNode,
  892. AtalkZipPacketIn,
  893. NULL,
  894. DDPPROTO_ANY,
  895. NULL,
  896. &pDdpAddr)))
  897. {
  898. LOG_ERRORONPORT(pPortDesc,
  899. EVENT_ATALK_OPENZIPSOCKET,
  900. 0,
  901. NULL,
  902. 0);
  903. AtalkNodeReleaseOnPort(pPortDesc, pAtalkNode);
  904. result = FALSE;
  905. break;
  906. }
  907. // mark the fact that this is an "internal" socket
  908. pDdpAddr->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  909. if (!(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY))
  910. {
  911. // Get the default zone
  912. AtalkZipGetNetworkInfoForNode(pPortDesc, &pAtalkNode->an_NodeAddr, TRUE);
  913. // Validate the desired zone
  914. AtalkZipGetNetworkInfoForNode(pPortDesc, &pAtalkNode->an_NodeAddr, FALSE);
  915. }
  916. // If nobody was out there and our tentative Node was in the
  917. // startup range and our caller doesn't want to be there, return
  918. // an error now.
  919. //
  920. // Note: this means that we were trying to start the router on
  921. // a non-seeding port, and since there is not router on the net,
  922. // it means the net is not seeded and so, we exit.
  923. if (inStartupRange &&
  924. !(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY) &&
  925. !AllowStartupRange)
  926. {
  927. LOG_ERRORONPORT(pPortDesc,
  928. EVENT_ATALK_STARTUPRANGENODE,
  929. 0,
  930. NULL,
  931. 0);
  932. AtalkNodeReleaseOnPort(pPortDesc, pAtalkNode);
  933. result = FALSE;
  934. break;
  935. }
  936. // If we have seen SeenRouterRecently is not true, that means we have
  937. // used the InitialNetworkRange to AARP. If now SeenRouterRecently is
  938. // true that means we have gotten the address in the InitialNetworkRange,
  939. // but now there is a seeded range on the net that we must use. So redo
  940. // the GetNode work.
  941. if ((pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY) &&
  942. !WITHIN_NETWORK_RANGE(newNode.atn_Network,
  943. &pPortDesc->pd_NetworkRange))
  944. {
  945. LOG_ERRORONPORT(pPortDesc,
  946. EVENT_ATALK_INITIALRANGENODE,
  947. 0,
  948. NULL,
  949. 0);
  950. // Release the node we obtained.
  951. AtalkNodeReleaseOnPort(pPortDesc, pAtalkNode);
  952. // Get another node and retry in the correct range.
  953. ASSERTMSG("NetworkRange still set to startup!\n",
  954. pPortDesc->pd_NetworkRange.anr_FirstNetwork != UNKNOWN_NETWORK);
  955. foundNode = AtalkInitAarpForNodeInRange(pPortDesc,
  956. NULL, // not a dial-in client
  957. FALSE, // don't care
  958. pPortDesc->pd_NetworkRange,
  959. &newNode);
  960. if (foundNode)
  961. {
  962. ASSERTMSG("New node is not within NetworkRange!\n",
  963. WITHIN_NETWORK_RANGE(newNode.atn_Network,
  964. &pPortDesc->pd_NetworkRange));
  965. if (!ATALK_SUCCESS(AtalkInitNodeAllocate(pPortDesc, &pAtalkNode)))
  966. {
  967. result = FALSE;
  968. break;
  969. }
  970. // Use the allocated structure to set the info.
  971. // Thread this into the port structure.
  972. pAtalkNode->an_NodeAddr = newNode;
  973. // Reference the port for this node.
  974. AtalkPortReferenceByPtr(pPortDesc, &error);
  975. if (!ATALK_SUCCESS(error))
  976. {
  977. result = FALSE;
  978. AtalkFreeMemory(pAtalkNode);
  979. break;
  980. }
  981. // Now put it in the port descriptor
  982. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  983. pAtalkNode->an_Next = pPortDesc->pd_Nodes;
  984. pPortDesc->pd_Nodes = pAtalkNode;
  985. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  986. // Open the zip socket to be consistent
  987. if (!ATALK_SUCCESS(AtalkDdpOpenAddress(pPortDesc,
  988. ZONESINFORMATION_SOCKET,
  989. &newNode,
  990. AtalkZipPacketIn,
  991. NULL,
  992. DDPPROTO_ANY,
  993. NULL,
  994. &pDdpAddr)))
  995. {
  996. LOG_ERRORONPORT(pPortDesc,
  997. EVENT_ATALK_OPENZIPSOCKET,
  998. 0,
  999. NULL,
  1000. 0);
  1001. AtalkNodeReleaseOnPort(pPortDesc, pAtalkNode);
  1002. result = FALSE;
  1003. break;
  1004. }
  1005. // mark the fact that this is an "internal" socket
  1006. pDdpAddr->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  1007. }
  1008. }
  1009. } while (FALSE);
  1010. }
  1011. else
  1012. {
  1013. // Free the allocated node structure. This has not yet been
  1014. // inserted into the port descriptor, so we can just free it.
  1015. AtalkFreeMemory(pAtalkNode);
  1016. }
  1017. if (foundNode && result)
  1018. {
  1019. // All set!
  1020. ASSERT(ppAtalkNode != NULL);
  1021. *ppAtalkNode = pAtalkNode;
  1022. // atalkAarpEnterIntoAmt() expects to be called at DISPATCH_LEVEL. Make it so.
  1023. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1024. atalkAarpEnterIntoAmt(pPortDesc,
  1025. &newNode,
  1026. pPortDesc->pd_PortAddr,
  1027. MAX_HW_ADDR_LEN,
  1028. NULL,
  1029. 0);
  1030. KeLowerIrql(OldIrql);
  1031. }
  1032. return ((foundNode && result) ? ATALK_NO_ERROR : ATALK_FAILURE);
  1033. }
  1034. BOOLEAN
  1035. AtalkInitAarpForNodeInRange(
  1036. IN PPORT_DESCRIPTOR pPortDesc,
  1037. IN PVOID pRasConn,
  1038. IN BOOLEAN fThisIsPPP,
  1039. IN ATALK_NETWORKRANGE NetworkRange,
  1040. OUT PATALK_NODEADDR Node
  1041. )
  1042. /*++
  1043. Routine Description:
  1044. Arguments:
  1045. Return Value:
  1046. --*/
  1047. {
  1048. BYTE currentNode;
  1049. USHORT currentNetwork;
  1050. int firstNode, lastNode;
  1051. long netTry;
  1052. int nodeTry;
  1053. USHORT nodeWidth, nodeChange, nodeIndex;
  1054. USHORT netWidth, netChange, netIndex;
  1055. BOOLEAN found = FALSE;
  1056. // Pick the node number range we'll try for (we do not pay attention to the
  1057. // "ServerNode" concept for LocalTalk). Our node is obtained by the
  1058. // localtalk driver anyways.
  1059. firstNode = MIN_USABLE_ATALKNODE;
  1060. lastNode = MAX_EXT_ATALKNODE;
  1061. // Okay, now some fun starts. Plow through our options trying to find an
  1062. // unused extended node number.
  1063. // Compute the width of our network range, and pick a random start point.
  1064. netWidth = (USHORT)((NetworkRange.anr_LastNetwork + 1) - NetworkRange.anr_FirstNetwork);
  1065. netTry = GET_RANDOM(NetworkRange.anr_FirstNetwork, NetworkRange.anr_LastNetwork);
  1066. // Come up with a random decrement, making sure it's odd (to avoid repeats)
  1067. // and large enough to appear pretty random.
  1068. netChange = (USHORT)(GET_RANDOM(1, netWidth) | 1);
  1069. while ((netWidth % netChange == 0) ||
  1070. (!AtalkIsPrime((long)netChange)))
  1071. {
  1072. netChange += 2;
  1073. }
  1074. // Now walk trough the range decrementing the starting network by the
  1075. // choosen change (with wrap, of course) until we find an address or
  1076. // we've processed every available network in the range.
  1077. for (netIndex = 0; netIndex < netWidth; netIndex ++)
  1078. {
  1079. currentNetwork = (USHORT) netTry;
  1080. // Compute the width of our node range, and pick a random start point.
  1081. nodeWidth = (USHORT)((lastNode + 1) - firstNode);
  1082. nodeTry = (int)GET_RANDOM(firstNode, lastNode);
  1083. // Come up with a random decrement, making sure it's odd (to avoid repeats)
  1084. // and large enough to appear pretty random.
  1085. nodeChange = (USHORT)(GET_RANDOM(1, nodeWidth) | 1);
  1086. while ((nodeWidth % nodeChange == 0) || !(AtalkIsPrime((long)nodeChange)))
  1087. nodeChange += 2;
  1088. // Now walk trough the range decrementing the starting network by the
  1089. // choosen change (with wrap, of course) until we find an address or
  1090. // we've processed every available node in the range.
  1091. for (nodeIndex = 0; nodeIndex < nodeWidth; nodeIndex ++)
  1092. {
  1093. currentNode = (BYTE )nodeTry;
  1094. // Let AARP have a crack at it.
  1095. if ((found = atalkInitAarpForNode(pPortDesc,
  1096. pRasConn,
  1097. fThisIsPPP,
  1098. currentNetwork,
  1099. currentNode)))
  1100. {
  1101. break;
  1102. }
  1103. // Okay, try again, bump down with wrap.
  1104. nodeTry -= nodeChange;
  1105. while (nodeTry < firstNode)
  1106. nodeTry += nodeWidth;
  1107. } // Node number loop
  1108. // If we found a node, break on thru to the other side.
  1109. if (found)
  1110. break;
  1111. // Okay, try again, bump down with wrap.
  1112. netTry -= netChange;
  1113. while (netTry < (long)NetworkRange.anr_FirstNetwork)
  1114. netTry += netWidth;
  1115. } // Network number loop
  1116. // Okay if we found one return all's well, otherwise no luck.
  1117. if (found)
  1118. {
  1119. if (Node != NULL)
  1120. {
  1121. Node->atn_Network = currentNetwork;
  1122. Node->atn_Node = currentNode;
  1123. }
  1124. }
  1125. return found;
  1126. } // AarpForNodeInRange
  1127. LOCAL BOOLEAN
  1128. atalkInitAarpForNode(
  1129. IN PPORT_DESCRIPTOR pPortDesc,
  1130. IN PVOID pRasConn,
  1131. IN BOOLEAN fThisIsPPP,
  1132. IN USHORT Network,
  1133. IN BYTE Node
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. Arguments:
  1138. Return Value:
  1139. --*/
  1140. {
  1141. SHORT probeAttempt;
  1142. PBUFFER_DESC pBuffDesc;
  1143. PVOID pTmpConn;
  1144. PATCPCONN pAtcpConn;
  1145. PARAPCONN pArapConn;
  1146. ATALK_NODEADDR tryNode;
  1147. KIRQL OldIrql;
  1148. PKEVENT pWaitEvent;
  1149. DWORD dwFlags;
  1150. BOOLEAN nodeInUse;
  1151. BOOLEAN fNoOneHasResponded=TRUE;
  1152. BOOLEAN fPPPConn;
  1153. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO,
  1154. ("atalkAarpForNode: AARPing for %x.%x on port %Z\n",
  1155. Network, Node, &pPortDesc->pd_AdapterKey));
  1156. // First make sure we don't own this node.
  1157. tryNode.atn_Network = Network;
  1158. tryNode.atn_Node = Node;
  1159. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1160. nodeInUse = AtalkNodeExistsOnPort(pPortDesc, &tryNode);
  1161. KeLowerIrql(OldIrql);
  1162. if (nodeInUse)
  1163. {
  1164. return(FALSE);
  1165. }
  1166. // is this node used by one of the dial in clients?
  1167. if ((pTmpConn = FindAndRefRasConnByAddr(tryNode, &dwFlags, &fPPPConn)) != NULL)
  1168. {
  1169. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO,
  1170. ("atalkAarpForNode: %x.%x already a dial in client (%lx)\n",
  1171. Network, Node, pTmpConn));
  1172. // our dial-in clients can only be in the network range of the
  1173. // default port
  1174. ASSERT(pPortDesc == AtalkDefaultPort);
  1175. if (fPPPConn)
  1176. {
  1177. ASSERT(((PATCPCONN)pTmpConn)->Signature == ATCPCONN_SIGNATURE);
  1178. DerefPPPConn((PATCPCONN)pTmpConn);
  1179. }
  1180. else
  1181. {
  1182. ASSERT(((PARAPCONN)pTmpConn)->Signature == ARAPCONN_SIGNATURE);
  1183. DerefArapConn((PARAPCONN)pTmpConn);
  1184. }
  1185. return(FALSE);
  1186. }
  1187. pAtcpConn = NULL;
  1188. pArapConn = NULL;
  1189. //
  1190. // if we are acquiring a node addr for a dial-in client...
  1191. //
  1192. if (pRasConn != NULL)
  1193. {
  1194. if (fThisIsPPP)
  1195. {
  1196. pAtcpConn = (PATCPCONN)pRasConn;
  1197. }
  1198. else
  1199. {
  1200. pArapConn = (PARAPCONN)pRasConn;
  1201. }
  1202. }
  1203. // PPP client?
  1204. if (pAtcpConn)
  1205. {
  1206. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  1207. pAtcpConn->NetAddr.atn_Network = Network;
  1208. pAtcpConn->NetAddr.atn_Node = Node;
  1209. pAtcpConn->Flags &= ~ATCP_NODE_IN_USE;
  1210. pWaitEvent = &pAtcpConn->NodeAcquireEvent;
  1211. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  1212. }
  1213. // nope, ARAP client?
  1214. else if (pArapConn)
  1215. {
  1216. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1217. pArapConn->NetAddr.atn_Network = Network;
  1218. pArapConn->NetAddr.atn_Node = Node;
  1219. pArapConn->Flags &= ~ARAP_NODE_IN_USE;
  1220. pWaitEvent = &pArapConn->NodeAcquireEvent;
  1221. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1222. }
  1223. // no, this is node acquisition for one of the server nodes
  1224. else
  1225. {
  1226. // Use AARP to probe for a particular network/node address.
  1227. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1228. pPortDesc->pd_Flags &= ~PD_NODE_IN_USE;
  1229. pPortDesc->pd_TentativeNodeAddr.atn_Network = Network;
  1230. pPortDesc->pd_TentativeNodeAddr.atn_Node = Node;
  1231. pWaitEvent = &pPortDesc->pd_NodeAcquireEvent;
  1232. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1233. }
  1234. fNoOneHasResponded = TRUE;
  1235. // Build the packet and blast it out the specified number of times.
  1236. for (probeAttempt = 0;
  1237. ((probeAttempt < pPortDesc->pd_AarpProbes) && (fNoOneHasResponded));
  1238. probeAttempt ++)
  1239. {
  1240. pBuffDesc = BUILD_AARPPROBE(pPortDesc, MAX_HW_ADDR_LEN, tryNode);
  1241. if (pBuffDesc == NULL)
  1242. {
  1243. RES_LOG_ERROR();
  1244. break;
  1245. }
  1246. if (!ATALK_SUCCESS(AtalkNdisSendPacket(pPortDesc,
  1247. pBuffDesc,
  1248. AtalkAarpSendComplete,
  1249. NULL)))
  1250. {
  1251. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  1252. ("atalkAarpForNode: AtalkNdisSendPacket failed while AARPing for %x.%x\n",
  1253. Network, Node));
  1254. // We allocated the packet.
  1255. AtalkAarpSendComplete(NDIS_STATUS_FAILURE, pBuffDesc, NULL);
  1256. break;
  1257. }
  1258. AtalkWaitTE(pWaitEvent, AARP_PROBE_TIMER_MS);
  1259. // node addr for a PPP client?
  1260. if (pAtcpConn)
  1261. {
  1262. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  1263. if (pAtcpConn->Flags & ATCP_NODE_IN_USE)
  1264. {
  1265. fNoOneHasResponded = FALSE;
  1266. }
  1267. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  1268. }
  1269. // node addr for a ARAP client?
  1270. else if (pArapConn)
  1271. {
  1272. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1273. if (pArapConn->Flags & ARAP_NODE_IN_USE)
  1274. {
  1275. fNoOneHasResponded = FALSE;
  1276. }
  1277. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1278. }
  1279. // nope, node addr for one of the server nodes
  1280. else
  1281. {
  1282. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1283. if (pPortDesc->pd_Flags & PD_NODE_IN_USE)
  1284. {
  1285. fNoOneHasResponded = FALSE;
  1286. }
  1287. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1288. }
  1289. } // Probe attempts loop
  1290. // We win if the current tentenative node has not been used
  1291. // (i.e. no one responds to our probes)
  1292. return (fNoOneHasResponded);
  1293. } // atalkAarpForNode
  1294. LOCAL VOID
  1295. atalkAarpEnterIntoAmt(
  1296. IN PPORT_DESCRIPTOR pPortDesc,
  1297. IN PATALK_NODEADDR pSrcNode,
  1298. IN PBYTE SrcAddr,
  1299. IN SHORT AddrLen,
  1300. IN PBYTE RouteInfo,
  1301. IN SHORT RouteInfoLen
  1302. )
  1303. /*++
  1304. Routine Description:
  1305. Arguments:
  1306. Return Value:
  1307. --*/
  1308. {
  1309. int index;
  1310. PAMT pAmt, *ppAmt;
  1311. if ((pSrcNode->atn_Node < MIN_USABLE_ATALKNODE) ||
  1312. (pSrcNode->atn_Node > MAX_USABLE_ATALKNODE) ||
  1313. (pSrcNode->atn_Network < FIRST_VALID_NETWORK) ||
  1314. (pSrcNode->atn_Network > LAST_VALID_NETWORK))
  1315. {
  1316. UCHAR AtalkAndMacAddress[sizeof(ATALK_NODEADDR) + MAX_HW_ADDR_LEN];
  1317. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  1318. ("atalkAarpEnterIntoAmt: Bad Node %x, %x\n",
  1319. pSrcNode->atn_Node, pSrcNode->atn_Network));
  1320. RtlCopyMemory(AtalkAndMacAddress, pSrcNode, sizeof(ATALK_NODEADDR));
  1321. RtlCopyMemory(AtalkAndMacAddress + sizeof(ATALK_NODEADDR), SrcAddr, MAX_HW_ADDR_LEN);
  1322. LOG_ERRORONPORT(pPortDesc,
  1323. EVENT_ATALK_AMT_INVALIDSOURCE,
  1324. 0,
  1325. AtalkAndMacAddress,
  1326. sizeof(AtalkAndMacAddress));
  1327. return;
  1328. }
  1329. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO,
  1330. ("AtalkAarpEnterIntoAmt: Entering %x.%x in amt\n",
  1331. pSrcNode->atn_Network, pSrcNode->atn_Node));
  1332. // Do we already know about this mapping?
  1333. index = HASH_ATALK_NODE(pSrcNode) & (PORT_AMT_HASH_SIZE - 1);
  1334. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1335. for (ppAmt = &pPortDesc->pd_Amt[index];
  1336. (pAmt = *ppAmt) != NULL;
  1337. ppAmt = &pAmt->amt_Next)
  1338. {
  1339. ASSERT(VALID_AMT(pAmt));
  1340. if (ATALK_NODES_EQUAL(pSrcNode, &pAmt->amt_Target))
  1341. {
  1342. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO,
  1343. ("atalkAarpEnterIntoAmt: Address %x.%x exists in tables\n",
  1344. pSrcNode->atn_Network, pSrcNode->atn_Node));
  1345. if ((pAmt->amt_RouteInfoLen == 0) ^ (RouteInfoLen == 0))
  1346. {
  1347. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_WARN,
  1348. ("atalkAarpEnterIntoAmt: %x.%x has wrong routing info\n",
  1349. pSrcNode->atn_Network, pSrcNode->atn_Node));
  1350. *ppAmt = pAmt->amt_Next;
  1351. AtalkBPFreeBlock(pAmt);
  1352. pAmt = NULL;
  1353. }
  1354. break;
  1355. }
  1356. }
  1357. // If not, allocate a new mapping Node.
  1358. if (pAmt == NULL)
  1359. {
  1360. BLKID BlkId;
  1361. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_WARN,
  1362. ("atalkAarpEnterIntoAmt: Address %x.%x DOES NOT exist in tables\n",
  1363. pSrcNode->atn_Network, pSrcNode->atn_Node));
  1364. ASSERT(RouteInfoLen <= TLAP_MAX_ROUTING_BYTES);
  1365. BlkId = BLKID_AMT;
  1366. if (RouteInfoLen != 0)
  1367. BlkId = BLKID_AMT_ROUTE;
  1368. if ((pAmt = (PAMT)AtalkBPAllocBlock(BlkId)) != NULL)
  1369. {
  1370. #if DBG
  1371. pAmt->amt_Signature = AMT_SIGNATURE;
  1372. #endif
  1373. // Link it in. Fill in below
  1374. pAmt->amt_Target.atn_Network = pSrcNode->atn_Network;
  1375. pAmt->amt_Target.atn_Node = pSrcNode->atn_Node;
  1376. pAmt->amt_Next = pPortDesc->pd_Amt[index];
  1377. pPortDesc->pd_Amt[index] = pAmt;
  1378. }
  1379. }
  1380. if (pAmt != NULL)
  1381. {
  1382. // Update mapping table! Do this if we knew about the mapping OR
  1383. // if we allocated a new node
  1384. ASSERTMSG("HWAddrLen is not right!\n", (AddrLen == MAX_HW_ADDR_LEN));
  1385. RtlCopyMemory(pAmt->amt_HardwareAddr, SrcAddr, AddrLen);
  1386. ASSERTMSG("RouteLen is not right!\n", (RouteInfoLen <= MAX_ROUTING_BYTES));
  1387. if (RouteInfoLen > 0)
  1388. RtlCopyMemory((PBYTE)pAmt + sizeof(AMT), RouteInfo, RouteInfoLen);
  1389. pAmt->amt_RouteInfoLen = (BYTE)RouteInfoLen;
  1390. pAmt->amt_Age = 0;
  1391. }
  1392. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1393. }
  1394. VOID
  1395. AtalkAarpReleaseAmt(
  1396. IN OUT PPORT_DESCRIPTOR pPortDesc
  1397. )
  1398. /*++
  1399. Routine Description:
  1400. Arguments:
  1401. Return Value:
  1402. --*/
  1403. {
  1404. int index;
  1405. PAMT pAmt, *ppAmt;
  1406. // Free up all the AMT entries. No need to acquire spinlock at this
  1407. // point. We are unloading and all binding etc are gone.
  1408. for (index = 0; index < PORT_AMT_HASH_SIZE; index ++)
  1409. {
  1410. for (ppAmt = &pPortDesc->pd_Amt[index];
  1411. (pAmt = *ppAmt) != NULL;
  1412. NOTHING)
  1413. {
  1414. ASSERT(VALID_AMT(pAmt));
  1415. *ppAmt = pAmt->amt_Next;
  1416. AtalkBPFreeBlock(pAmt);
  1417. }
  1418. }
  1419. }
  1420. VOID
  1421. AtalkAarpReleaseBrc(
  1422. IN OUT PPORT_DESCRIPTOR pPortDesc
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. Arguments:
  1427. Return Value:
  1428. --*/
  1429. {
  1430. int index;
  1431. PBRE pBre, *ppBre;
  1432. // Free up all the BRC entries. No need to acquire spinlock at this
  1433. // point. We are unloading and all binding etc are gone.
  1434. for (index = 0; index < PORT_BRC_HASH_SIZE; index ++)
  1435. {
  1436. for (ppBre = &pPortDesc->pd_Brc[index];
  1437. (pBre = *ppBre) != NULL;
  1438. NOTHING)
  1439. {
  1440. *ppBre = pBre->bre_Next;
  1441. AtalkBPFreeBlock(pBre);
  1442. }
  1443. }
  1444. }
  1445. LONG FASTCALL
  1446. AtalkAarpAmtTimer(
  1447. IN PTIMERLIST pTimer,
  1448. IN BOOLEAN TimerShuttingDown
  1449. )
  1450. /*++
  1451. Routine Description:
  1452. Arguments:
  1453. Return Value:
  1454. --*/
  1455. {
  1456. PAMT pAmt, *ppAmt;
  1457. PPORT_DESCRIPTOR pPortDesc;
  1458. int index;
  1459. pPortDesc = (PPORT_DESCRIPTOR)CONTAINING_RECORD(pTimer, PORT_DESCRIPTOR, pd_AmtTimer);
  1460. ASSERT(VALID_PORT(pPortDesc));
  1461. ASSERT(EXT_NET(pPortDesc));
  1462. // Walk though all address mapping entries on this port aging the entries.
  1463. // We need to protect the mapping tables with critical sections, but don't
  1464. // stay in a critical section too long.
  1465. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1466. if (TimerShuttingDown ||
  1467. ((pPortDesc->pd_Flags & PD_CLOSING) != 0))
  1468. {
  1469. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1470. // Remove the reference we added to this port at the time of
  1471. // starting the timer. Return;
  1472. AtalkPortDereferenceDpc(pPortDesc);
  1473. return ATALK_TIMER_NO_REQUEUE;
  1474. }
  1475. for (index = 0; index < PORT_AMT_HASH_SIZE; index ++)
  1476. {
  1477. for (ppAmt = &pPortDesc->pd_Amt[index];
  1478. (pAmt = *ppAmt) != NULL;
  1479. NOTHING)
  1480. {
  1481. ASSERT(VALID_AMT(pAmt));
  1482. if (pAmt->amt_Age < AMT_MAX_AGE)
  1483. {
  1484. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_INFO,
  1485. ("atalkAarpAmtTimer: Entry for %x.%x %lx OK\n",
  1486. pAmt->amt_Target.atn_Network, pAmt->amt_Target.atn_Node,
  1487. pAmt));
  1488. pAmt->amt_Age ++;
  1489. ppAmt = &pAmt->amt_Next;
  1490. }
  1491. else
  1492. {
  1493. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_WARN,
  1494. ("atalkAarpAmtTimer: Freeing node %x.%x from list\n",
  1495. pAmt->amt_Target.atn_Network,
  1496. pAmt->amt_Target.atn_Node));
  1497. *ppAmt = pAmt->amt_Next;
  1498. AtalkBPFreeBlock(pAmt);
  1499. }
  1500. }
  1501. }
  1502. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1503. return ATALK_TIMER_REQUEUE;
  1504. }
  1505. LONG FASTCALL
  1506. AtalkAarpBrcTimer(
  1507. IN PTIMERLIST pTimer,
  1508. IN BOOLEAN TimerShuttingDown
  1509. )
  1510. /*++
  1511. Routine Description:
  1512. Arguments:
  1513. Return Value:
  1514. --*/
  1515. {
  1516. int index;
  1517. PPORT_DESCRIPTOR pPortDesc;
  1518. BOOLEAN DerefPort = FALSE;
  1519. pPortDesc = (PPORT_DESCRIPTOR)CONTAINING_RECORD(pTimer, PORT_DESCRIPTOR, pd_BrcTimer);
  1520. ASSERT(VALID_PORT(pPortDesc));
  1521. ASSERT(EXT_NET(pPortDesc));
  1522. // Walk though all best router entries on this port aging the entries.
  1523. // We need to protect the brc tables with critical sections, but don't
  1524. // stay in a critical section too long.
  1525. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1526. if (TimerShuttingDown ||
  1527. ((pPortDesc->pd_Flags & PD_CLOSING) != 0))
  1528. {
  1529. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1530. // Remove the reference we added to this port at the time of
  1531. // starting the timer. Return;
  1532. AtalkPortDereferenceDpc(pPortDesc);
  1533. return ATALK_TIMER_NO_REQUEUE;
  1534. }
  1535. for (index = 0; index < PORT_BRC_HASH_SIZE; index ++)
  1536. {
  1537. PBRE pBre, *ppBre;
  1538. for (ppBre = &pPortDesc->pd_Brc[index];
  1539. (pBre = *ppBre) != NULL;
  1540. NOTHING)
  1541. {
  1542. if (pBre->bre_Age < BRC_MAX_AGE)
  1543. {
  1544. pBre->bre_Age ++;
  1545. ppBre = &pBre->bre_Next;
  1546. }
  1547. else
  1548. {
  1549. *ppBre = pBre->bre_Next;
  1550. AtalkBPFreeBlock(pBre);
  1551. }
  1552. }
  1553. }
  1554. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1555. return ATALK_TIMER_REQUEUE;
  1556. }
  1557. PBUFFER_DESC
  1558. AtalkAarpBuildPacket(
  1559. IN PPORT_DESCRIPTOR pPortDesc,
  1560. IN USHORT Type,
  1561. IN USHORT HardwareLen,
  1562. IN PBYTE SrcHardwareAddr,
  1563. IN ATALK_NODEADDR SrcLogicalAddr,
  1564. IN PBYTE DestHardwareAddr,
  1565. IN ATALK_NODEADDR DestLogicalAddr,
  1566. IN PBYTE TrueDest,
  1567. IN PBYTE RouteInfo,
  1568. IN USHORT RouteInfoLen
  1569. )
  1570. /*++
  1571. Routine Description:
  1572. Arguments:
  1573. Return Value:
  1574. --*/
  1575. {
  1576. PBYTE aarpData;
  1577. USHORT linkLen;
  1578. PBUFFER_DESC pBuffDesc = NULL;
  1579. BYTE protocolLength = AARP_PROTO_ADDR_LEN;
  1580. PVOID pRasConn;
  1581. DWORD dwFlags;
  1582. BOOLEAN fThisIsPPP;
  1583. // Read only.
  1584. static BYTE zeroAddr[MAX_HW_ADDR_LEN] =
  1585. {
  1586. 0, 0, 0, 0, 0, 0
  1587. };
  1588. #if DBG
  1589. // make sure we aren't sending AARP request/probe for our own dial-in client
  1590. if ((Type == AARP_REQUEST) || (Type == AARP_PROBE))
  1591. {
  1592. pRasConn = FindAndRefRasConnByAddr(DestLogicalAddr, &dwFlags, &fThisIsPPP);
  1593. if (pRasConn)
  1594. {
  1595. if (fThisIsPPP)
  1596. {
  1597. ASSERT(((PATCPCONN)pRasConn)->Signature == ATCPCONN_SIGNATURE);
  1598. if (dwFlags & ATCP_NODE_IN_USE)
  1599. {
  1600. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  1601. ("AtalkAarpBuildPacket: PPP client (%lx) owns %x.%x (Type=%x)\n",
  1602. pRasConn,DestLogicalAddr.atn_Network, DestLogicalAddr.atn_Node,Type));
  1603. }
  1604. DerefPPPConn((PATCPCONN)pRasConn);
  1605. }
  1606. else
  1607. {
  1608. ASSERT(((PARAPCONN)pRasConn)->Signature == ARAPCONN_SIGNATURE);
  1609. if (dwFlags & ARAP_NODE_IN_USE)
  1610. {
  1611. DBGPRINT(DBG_COMP_AARP, DBG_LEVEL_ERR,
  1612. ("AtalkAarpBuildPacket: ARA client (%lx) owns %x.%x (Type=%x)\n",
  1613. pRasConn,DestLogicalAddr.atn_Network, DestLogicalAddr.atn_Node,Type));
  1614. }
  1615. DerefArapConn((PARAPCONN)pRasConn);
  1616. }
  1617. }
  1618. }
  1619. #endif
  1620. // If no destination hardware address is specified, set it
  1621. // to all zeros.
  1622. if (DestHardwareAddr == NULL)
  1623. {
  1624. DestHardwareAddr = zeroAddr;
  1625. }
  1626. // Get a header buffer allocated from link routines. Tell it we want
  1627. // maximum aarp data size as the required size.
  1628. AtalkNdisAllocBuf(&pBuffDesc);
  1629. if (pBuffDesc == NULL)
  1630. {
  1631. return(pBuffDesc);
  1632. }
  1633. // Build the LAP header.
  1634. AtalkNdisBuildHdr(pPortDesc,
  1635. pBuffDesc->bd_CharBuffer,
  1636. linkLen,
  1637. AARP_MIN_DATA_SIZE,
  1638. TrueDest,
  1639. RouteInfo,
  1640. RouteInfoLen,
  1641. AARP_PROTOCOL);
  1642. aarpData = pBuffDesc->bd_CharBuffer + linkLen;
  1643. // Build the specified type of AARP packet with the specified information;
  1644. PUTSHORT2SHORT((PUSHORT)aarpData,
  1645. pPortDesc->pd_AarpHardwareType);
  1646. aarpData += sizeof(USHORT);
  1647. PUTSHORT2SHORT((PUSHORT)aarpData,
  1648. pPortDesc->pd_AarpProtocolType);
  1649. aarpData += sizeof(USHORT);
  1650. *aarpData++ = (BYTE)HardwareLen;
  1651. *aarpData++ = (BYTE)AARP_PROTO_ADDR_LEN;
  1652. PUTSHORT2SHORT((PUSHORT)aarpData, Type);
  1653. aarpData += sizeof(USHORT);
  1654. // Source hardware address.
  1655. RtlCopyMemory(aarpData, SrcHardwareAddr, HardwareLen);
  1656. aarpData += HardwareLen;
  1657. // Source logical address pad
  1658. *aarpData++ = 0;
  1659. // Network number
  1660. PUTSHORT2SHORT(aarpData, SrcLogicalAddr.atn_Network);
  1661. aarpData += sizeof(USHORT);
  1662. // Node number
  1663. *aarpData++ = SrcLogicalAddr.atn_Node;
  1664. // Destination hardware address.
  1665. RtlCopyMemory(aarpData, DestHardwareAddr, HardwareLen);
  1666. aarpData += HardwareLen;
  1667. // Destination logical address, null pad
  1668. *aarpData++ = 0;
  1669. // Network number
  1670. PUTSHORT2SHORT(aarpData, DestLogicalAddr.atn_Network);
  1671. aarpData += sizeof(USHORT);
  1672. // Node number
  1673. *aarpData++ = DestLogicalAddr.atn_Node;
  1674. // Set length in the buffer descriptor. Pad it to max data size. Some devices seem
  1675. // to drop the aarp responses if they see less, Macs dictate their behavior.
  1676. // Also zero out the extra space.
  1677. AtalkSetSizeOfBuffDescData(pBuffDesc,
  1678. (SHORT)(aarpData - pBuffDesc->bd_CharBuffer + AARP_MAX_DATA_SIZE - AARP_MIN_DATA_SIZE));
  1679. RtlZeroMemory(aarpData, AARP_MAX_DATA_SIZE - AARP_MIN_DATA_SIZE);
  1680. return pBuffDesc;
  1681. }
  1682. LOCAL VOID FASTCALL
  1683. atalkAarpTuneRouteInfo(
  1684. IN PPORT_DESCRIPTOR pPortDesc,
  1685. IN OUT PBYTE RouteInfo
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. Arguments:
  1690. Return Value:
  1691. --*/
  1692. {
  1693. // Given an incoming TokenRing routing info, tune it to make it valid
  1694. // for outing routing info. Do this in place!
  1695. ASSERT(pPortDesc->pd_PortType == TLAP_PORT);
  1696. // Set to "non-broadcast" and invert "direction".
  1697. RouteInfo[0] &= TLAP_NON_BROADCAST_MASK;
  1698. RouteInfo[1] ^= TLAP_DIRECTION_MASK;
  1699. }
  1700. #if DBG
  1701. VOID
  1702. AtalkAmtDumpTable(
  1703. VOID
  1704. )
  1705. {
  1706. int j, k;
  1707. KIRQL OldIrql;
  1708. PPORT_DESCRIPTOR pPortDesc;
  1709. PAMT pAmt;
  1710. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  1711. for (pPortDesc = AtalkPortList;
  1712. pPortDesc != NULL;
  1713. pPortDesc = pPortDesc = pPortDesc->pd_Next)
  1714. {
  1715. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  1716. ("AMT Table for port %Z\n", &pPortDesc->pd_AdapterKey));
  1717. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1718. for (j = 0; j < PORT_AMT_HASH_SIZE; j++)
  1719. {
  1720. for (pAmt = pPortDesc->pd_Amt[j];
  1721. pAmt != NULL;
  1722. pAmt = pAmt->amt_Next)
  1723. {
  1724. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  1725. ("\t%d: %lx.%lx", j,
  1726. pAmt->amt_Target.atn_Network, pAmt->amt_Target.atn_Node));
  1727. for (k = 0; k < MAX_HW_ADDR_LEN; k++)
  1728. {
  1729. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  1730. ("%02x", pAmt->amt_HardwareAddr[k]));
  1731. }
  1732. if (pAmt->amt_RouteInfoLen != 0)
  1733. {
  1734. PBYTE pRouteInfo;
  1735. pRouteInfo = (PBYTE)pAmt + sizeof(AMT);
  1736. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  1737. (" ("));
  1738. for (k = 0; k < pAmt->amt_RouteInfoLen; k++)
  1739. {
  1740. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  1741. (" %02x", pRouteInfo[k]));
  1742. }
  1743. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL, (" )"));
  1744. }
  1745. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL, ("\n"));
  1746. }
  1747. }
  1748. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1749. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL, ("\n"));
  1750. }
  1751. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  1752. }
  1753. #endif
  1754.