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.

1903 lines
49 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. nbp.c
  5. Abstract:
  6. This module contains nbp 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 FILENUM NBP
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE_NZ, AtalkNbpAction)
  19. #pragma alloc_text(PAGE_NZ, atalkNbpLinkPendingNameInList)
  20. #pragma alloc_text(PAGE_NZ, atalkNbpSendRequest)
  21. #endif
  22. /*** AtalkNbpPacketIn
  23. *
  24. */
  25. VOID
  26. AtalkNbpPacketIn(
  27. IN PPORT_DESCRIPTOR pPortDesc,
  28. IN PDDP_ADDROBJ pDdpAddr,
  29. IN PBYTE pPkt,
  30. IN USHORT PktLen,
  31. IN PATALK_ADDR pSrcAddr,
  32. IN PATALK_ADDR pDstAddr,
  33. IN ATALK_ERROR ErrorCode,
  34. IN BYTE DdpType,
  35. IN PVOID pHandlerCtx,
  36. IN BOOLEAN OptimizedPath,
  37. IN PVOID OptimizeCtx
  38. )
  39. {
  40. PPEND_NAME pPendName;
  41. PATALK_NODE pNode;
  42. TIME TimeS, TimeE, TimeD;
  43. PNBPHDR pNbpHdr = (PNBPHDR)pPkt;
  44. PRTE pRte;
  45. SHORT i, NbpId, NbpCmd, TupleCnt;
  46. PNBPTUPLE pNbpTuple = NULL, pInBufTuple = NULL;
  47. BOOLEAN DefZone = FALSE, RestartTimer = FALSE;
  48. BOOLEAN fWeCancelledTimer = TRUE;
  49. BOOLEAN Found;
  50. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  51. TimeS = KeQueryPerformanceCounter(NULL);
  52. do
  53. {
  54. if ((ErrorCode == ATALK_SOCKET_CLOSED) || (DdpType != DDPPROTO_NBP))
  55. break;
  56. else if ((ErrorCode != ATALK_NO_ERROR) || (PktLen < sizeof(NBPHDR)))
  57. {
  58. break;
  59. }
  60. // Get NBP header information and decide what to do
  61. NbpCmd = (SHORT)((pNbpHdr->_CmdAndTupleCnt >> 4) & 0x0F);
  62. TupleCnt = (SHORT)(pNbpHdr->_CmdAndTupleCnt & 0x0F);
  63. NbpId = (SHORT)pNbpHdr->_NbpId;
  64. if ((pNbpTuple = AtalkAllocMemory(sizeof(NBPTUPLE))) == NULL)
  65. {
  66. TMPLOGERR();
  67. break;
  68. }
  69. switch (NbpCmd)
  70. {
  71. case NBP_LOOKUP:
  72. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  73. ("atalkNbpPacketIn: Cmd Lookup\n"));
  74. if ((TupleCnt == 1) &&
  75. (atalkNbpDecodeTuple(pPkt + sizeof(NBPHDR),
  76. (USHORT)(PktLen - sizeof(NBPHDR)),
  77. pNbpTuple) > 0))
  78. {
  79. atalkNbpLookupNames(pPortDesc, pDdpAddr, pNbpTuple, NbpId);
  80. }
  81. else
  82. {
  83. #if 0
  84. AtalkLogBadPacket(pPortDesc,
  85. pSrcAddr,
  86. pDstAddr,
  87. pPkt,
  88. PktLen);
  89. #endif
  90. break;
  91. }
  92. break;
  93. case NBP_BROADCAST_REQUEST:
  94. case NBP_FORWARD_REQUEST:
  95. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  96. ("atalkNbpPacketIn: Cmd %sRequest\n",
  97. (NbpCmd == NBP_BROADCAST_REQUEST) ? "Broadcast" : "Forward"));
  98. // We don't care if we are not a router
  99. if ((pPortDesc->pd_Flags & PD_ROUTER_RUNNING) == 0)
  100. break;
  101. if (TupleCnt != 1)
  102. {
  103. AtalkLogBadPacket(pPortDesc,
  104. pSrcAddr,
  105. pDstAddr,
  106. pPkt,
  107. PktLen);
  108. break;
  109. }
  110. if (atalkNbpDecodeTuple(pPkt + sizeof(NBPHDR),
  111. (USHORT)(PktLen - sizeof(NBPHDR)),
  112. pNbpTuple) == 0)
  113. {
  114. AtalkLogBadPacket(pPortDesc,
  115. pSrcAddr,
  116. pDstAddr,
  117. pPkt,
  118. PktLen);
  119. break;
  120. }
  121. if ((pNbpTuple->tpl_ZoneLen == 0) ||
  122. ((pNbpTuple->tpl_Zone[0] == '*') && (pNbpTuple->tpl_ZoneLen == 1)))
  123. DefZone = TRUE;
  124. if (EXT_NET(pPortDesc))
  125. {
  126. if (DefZone)
  127. {
  128. AtalkLogBadPacket(pPortDesc,
  129. pSrcAddr,
  130. pDstAddr,
  131. pPkt,
  132. PktLen);
  133. break;
  134. }
  135. }
  136. else // Non-extended network
  137. {
  138. if (DefZone)
  139. {
  140. if (pPortDesc->pd_NetworkRange.anr_FirstNetwork != pSrcAddr->ata_Network)
  141. {
  142. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_ERR,
  143. ("AtalkNbpPacketIn: LT Port, '*' zone - SrcAddr %d.%d, Net %d\n",
  144. pSrcAddr->ata_Network, pSrcAddr->ata_Node,
  145. pPortDesc->pd_NetworkRange.anr_FirstNetwork));
  146. AtalkLogBadPacket(pPortDesc,
  147. pSrcAddr,
  148. pDstAddr,
  149. pPkt,
  150. PktLen);
  151. break;
  152. }
  153. if (!(pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE))
  154. break;
  155. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  156. pNbpTuple->tpl_ZoneLen = pPortDesc->pd_DesiredZone->zn_ZoneLen;
  157. RtlCopyMemory(pNbpTuple->tpl_Zone,
  158. pPortDesc->pd_DesiredZone->zn_Zone,
  159. pPortDesc->pd_DesiredZone->zn_ZoneLen);
  160. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  161. }
  162. }
  163. // For a forward request send a lookup datagram
  164. if (NbpCmd == NBP_FORWARD_REQUEST)
  165. {
  166. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  167. ("AtalkNbpPacketIn: Sending NbpLookup for a NbpForwardRequest\n"));
  168. atalkNbpSendLookupDatagram(pPortDesc, pDdpAddr, NbpId, pNbpTuple);
  169. break;
  170. }
  171. // We have a broadcast request. Walk through the routing tables
  172. // sending either a forward request or a lookup (broadcast) to
  173. // each network that contains the specified zone
  174. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock);
  175. for (i = 0;i < NUM_RTMP_HASH_BUCKETS; i++)
  176. {
  177. for (pRte = AtalkRoutingTable[i];
  178. pRte != NULL;
  179. pRte = pRte->rte_Next)
  180. {
  181. ATALK_ERROR Status;
  182. // If the network is directly connected i.e. 0 hops away
  183. // use the zone-list in the PortDesc rather than the
  184. // routing table - the routing table may not be filled
  185. // in with a zone list (due to the normal ZipQuery mechanism)
  186. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  187. if (!(pRte->rte_Flags & RTE_ZONELIST_VALID))
  188. {
  189. if ((pRte->rte_NumHops != 0) ||
  190. !AtalkZoneNameOnList(pNbpTuple->tpl_Zone,
  191. pNbpTuple->tpl_ZoneLen,
  192. pRte->rte_PortDesc->pd_ZoneList))
  193. {
  194. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  195. continue;
  196. }
  197. }
  198. else if (!AtalkZoneNameOnList(pNbpTuple->tpl_Zone,
  199. pNbpTuple->tpl_ZoneLen,
  200. pRte->rte_ZoneList))
  201. {
  202. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  203. continue;
  204. }
  205. pRte->rte_RefCount ++;
  206. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  207. // If not a local network, send a forward request
  208. if (pRte->rte_NumHops != 0)
  209. {
  210. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  211. ("AtalkNbpPacketIn: Sending NbpForwardRequest for a broadcast\n"));
  212. // Do not hold the Rte lock during a DdpSend
  213. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  214. atalkNbpSendForwardRequest(pDdpAddr,
  215. pRte,
  216. NbpId,
  217. pNbpTuple);
  218. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock);
  219. AtalkRtmpDereferenceRte(pRte, TRUE);
  220. }
  221. else
  222. {
  223. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  224. ("AtalkNbpPacketIn: Sending Lookup for a broadcast\n"));
  225. // Send a lookup
  226. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  227. atalkNbpSendLookupDatagram(pRte->rte_PortDesc,
  228. NULL,
  229. NbpId,
  230. pNbpTuple);
  231. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock);
  232. AtalkRtmpDereferenceRte(pRte, TRUE);
  233. }
  234. }
  235. }
  236. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  237. break;
  238. case NBP_LOOKUP_REPLY:
  239. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  240. ("atalkNbpPacketIn: Cmd LookupReply\n"));
  241. // This had better be a response to a previous lookup
  242. // Look for a pending name on all open sockets on this node
  243. if (TupleCnt == 0)
  244. break;
  245. // Decode the tuple for Register/Confirm case
  246. if (atalkNbpDecodeTuple(pPkt + sizeof(NBPHDR),
  247. (USHORT)(PktLen - sizeof(NBPHDR)),
  248. pNbpTuple) == 0)
  249. {
  250. break;
  251. }
  252. pNode = pDdpAddr->ddpao_Node;
  253. ACQUIRE_SPIN_LOCK_DPC(&pNode->an_Lock);
  254. Found = FALSE;
  255. for (i = 0; (i < NODE_DDPAO_HASH_SIZE) && !Found; i++)
  256. {
  257. PDDP_ADDROBJ pSkt;
  258. for (pSkt = pNode->an_DdpAoHash[i];
  259. (pSkt != NULL) && !Found;
  260. pSkt = pSkt->ddpao_Next)
  261. {
  262. PPEND_NAME * ppPendName;
  263. ACQUIRE_SPIN_LOCK_DPC(&pSkt->ddpao_Lock);
  264. for (ppPendName = &pSkt->ddpao_PendNames;
  265. (pPendName = *ppPendName) != NULL;
  266. ppPendName = &pPendName->pdn_Next)
  267. {
  268. ASSERT (VALID_PENDNAME(pPendName));
  269. if (pPendName->pdn_Flags & PDN_CLOSING)
  270. {
  271. continue;
  272. }
  273. if (pPendName->pdn_NbpId == NbpId)
  274. {
  275. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  276. ("atalkNbpPacketIn: LookupReply Found name\n"));
  277. Found = TRUE;
  278. ACQUIRE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  279. pPendName->pdn_RefCount ++;
  280. RELEASE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  281. break;
  282. }
  283. }
  284. RELEASE_SPIN_LOCK_DPC(&pSkt->ddpao_Lock);
  285. }
  286. }
  287. RELEASE_SPIN_LOCK_DPC(&pNode->an_Lock);
  288. // If the timer fired just before we could find and cancel it
  289. if (pPendName == NULL)
  290. break;
  291. do
  292. {
  293. if (AtalkTimerCancelEvent(&pPendName->pdn_Timer, NULL))
  294. {
  295. // if the timer was successfully cancelled, take away
  296. // the reference for it
  297. atalkNbpDerefPendName(pPendName);
  298. RestartTimer = TRUE;
  299. }
  300. else
  301. {
  302. fWeCancelledTimer = FALSE;
  303. }
  304. if ((pPendName->pdn_Reason == FOR_REGISTER) ||
  305. (pPendName->pdn_Reason == FOR_CONFIRM))
  306. {
  307. BOOLEAN NoMatch;
  308. // Does the reply match the one we're trying to register ?
  309. NoMatch = ( (TupleCnt != 1) ||
  310. (pPendName->pdn_pRegdName == NULL) ||
  311. !AtalkFixedCompareCaseInsensitive(
  312. pPendName->pdn_pRegdName->rdn_Tuple.tpl_Object,
  313. pPendName->pdn_pRegdName->rdn_Tuple.tpl_ObjectLen,
  314. pNbpTuple->tpl_Object,
  315. pNbpTuple->tpl_ObjectLen) ||
  316. !AtalkFixedCompareCaseInsensitive(
  317. pPendName->pdn_pRegdName->rdn_Tuple.tpl_Type,
  318. pPendName->pdn_pRegdName->rdn_Tuple.tpl_TypeLen,
  319. pNbpTuple->tpl_Type,
  320. pNbpTuple->tpl_TypeLen));
  321. if (NoMatch)
  322. {
  323. if (TupleCnt != 1)
  324. AtalkLogBadPacket(pPortDesc,
  325. pSrcAddr,
  326. pDstAddr,
  327. pPkt,
  328. PktLen);
  329. break;
  330. }
  331. // If we are registering, we're done as someone already
  332. // has our name
  333. if (pPendName->pdn_Reason == FOR_REGISTER)
  334. {
  335. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  336. ("atalkNbpPacketIn: Register failure\n"));
  337. ACQUIRE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  338. pPendName->pdn_Status = ATALK_SHARING_VIOLATION;
  339. pPendName->pdn_Flags |= PDN_CLOSING;
  340. RELEASE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  341. if (fWeCancelledTimer)
  342. {
  343. atalkNbpDerefPendName(pPendName); // Take away creation ref
  344. }
  345. RestartTimer = FALSE;
  346. break;
  347. }
  348. // We're confirming, if no match get out
  349. if ((pPendName->pdn_ConfirmAddr.ata_Network != pNbpTuple->tpl_Address.ata_Network) ||
  350. (pPendName->pdn_ConfirmAddr.ata_Node != pNbpTuple->tpl_Address.ata_Node))
  351. {
  352. break;
  353. }
  354. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  355. ("atalkNbpPacketIn: Confirm success\n"));
  356. ACQUIRE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  357. pPendName->pdn_Status = ATALK_NO_ERROR;
  358. ((PNBP_CONFIRM_PARAMS)(pPendName->pdn_pActReq->ar_pParms))->ConfirmTuple.Address.Address =
  359. pNbpTuple->tpl_Address.ata_Address;
  360. if (pPendName->pdn_ConfirmAddr.ata_Socket != pNbpTuple->tpl_Address.ata_Socket)
  361. {
  362. pPendName->pdn_Status = ATALK_NEW_SOCKET;
  363. }
  364. pPendName->pdn_Flags |= PDN_CLOSING;
  365. RELEASE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  366. atalkNbpDerefPendName(pPendName); // Take away creation ref
  367. RestartTimer = FALSE;
  368. }
  369. else // FOR_LOOKUP
  370. {
  371. int i, j, tmp, NextTupleOff = sizeof(NBPHDR);
  372. BOOLEAN Done = FALSE;
  373. ULONG BytesCopied;
  374. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  375. ("atalkNbpPacketIn: Lookup searching...\n"));
  376. // Allocate space for an NBP tuple for copying and comparing
  377. // Failure to allocate can result in duplicates - so be it
  378. if (pInBufTuple == NULL)
  379. pInBufTuple = AtalkAllocMemory(sizeof(NBPTUPLE));
  380. for (i = 0; i < TupleCnt && !Done; i++)
  381. {
  382. BOOLEAN Duplicate = FALSE;
  383. // If we encounter a bad tuple, ignore the rest. Drop tuples which are
  384. // our names and we are set to drop them !!!
  385. if (((tmp = atalkNbpDecodeTuple(pPkt + NextTupleOff,
  386. (USHORT)(PktLen - NextTupleOff),
  387. pNbpTuple)) == 0) ||
  388. (AtalkFilterOurNames &&
  389. (((pNbpTuple->tpl_Address.ata_Network == AtalkUserNode1.atn_Network) &&
  390. (pNbpTuple->tpl_Address.ata_Node == AtalkUserNode1.atn_Node)) ||
  391. ((pNbpTuple->tpl_Address.ata_Network == AtalkUserNode2.atn_Network) &&
  392. (pNbpTuple->tpl_Address.ata_Node == AtalkUserNode2.atn_Node)))))
  393. break;
  394. NextTupleOff += tmp;
  395. ACQUIRE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  396. // Now walk through the tuples that we already picked
  397. // up and drop duplicates
  398. if (pInBufTuple != NULL)
  399. {
  400. for (j = 0; j < pPendName->pdn_TotalTuples; j++)
  401. {
  402. TdiCopyMdlToBuffer(pPendName->pdn_pAMdl,
  403. j * sizeof(NBPTUPLE),
  404. (PBYTE)pInBufTuple,
  405. 0,
  406. sizeof(NBPTUPLE),
  407. &BytesCopied);
  408. ASSERT (BytesCopied == sizeof(NBPTUPLE));
  409. if ((pInBufTuple->tpl_Address.ata_Network ==
  410. pNbpTuple->tpl_Address.ata_Network) &&
  411. (pInBufTuple->tpl_Address.ata_Node ==
  412. pNbpTuple->tpl_Address.ata_Node) &&
  413. (pInBufTuple->tpl_Address.ata_Socket ==
  414. pNbpTuple->tpl_Address.ata_Socket))
  415. {
  416. Duplicate = TRUE;
  417. break;
  418. }
  419. }
  420. if (Duplicate)
  421. {
  422. RELEASE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  423. continue;
  424. }
  425. }
  426. // We are guaranteed that there is space available
  427. // for another tuple.
  428. TdiCopyBufferToMdl((PBYTE)pNbpTuple,
  429. 0,
  430. sizeof(NBPTUPLE),
  431. pPendName->pdn_pAMdl,
  432. pPendName->pdn_TotalTuples * sizeof(NBPTUPLE),
  433. &BytesCopied);
  434. ASSERT (BytesCopied == sizeof(NBPTUPLE));
  435. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  436. ("atalkNbpPacketIn: Lookup, found a tuple\n"));
  437. pPendName->pdn_TotalTuples ++;
  438. if ((pPendName->pdn_TotalTuples == pPendName->pdn_MaxTuples) ||
  439. (pPendName->pdn_MdlLength -
  440. (pPendName->pdn_TotalTuples * sizeof(NBPTUPLE)) <
  441. sizeof(NBPTUPLE)))
  442. {
  443. Done = TRUE;
  444. ((PNBP_LOOKUP_PARAMS)(pPendName->pdn_pActReq->ar_pParms))->NoTuplesRead =
  445. pPendName->pdn_TotalTuples;
  446. pPendName->pdn_Status = ATALK_NO_ERROR;
  447. pPendName->pdn_Flags |= PDN_CLOSING;
  448. RestartTimer = FALSE;
  449. }
  450. RELEASE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  451. if (Done)
  452. {
  453. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  454. ("atalkNbpPacketIn: Lookup calling completion\n"));
  455. if (fWeCancelledTimer)
  456. {
  457. atalkNbpDerefPendName(pPendName); // Take away creation ref
  458. }
  459. break;
  460. }
  461. }
  462. }
  463. } while (FALSE);
  464. if (RestartTimer)
  465. {
  466. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  467. ("atalkNbpPacketIn: Restarting timer\n"));
  468. ACQUIRE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  469. pPendName->pdn_RefCount ++;
  470. RELEASE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  471. AtalkTimerScheduleEvent(&pPendName->pdn_Timer);
  472. }
  473. atalkNbpDerefPendName(pPendName);
  474. break;
  475. default:
  476. AtalkLogBadPacket(pPortDesc,
  477. pSrcAddr,
  478. pDstAddr,
  479. pPkt,
  480. PktLen);
  481. break;
  482. }
  483. } while (FALSE);
  484. if (pNbpTuple != NULL)
  485. AtalkFreeMemory(pNbpTuple);
  486. if (pInBufTuple != NULL)
  487. AtalkFreeMemory(pInBufTuple);
  488. TimeE = KeQueryPerformanceCounter(NULL);
  489. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  490. INTERLOCKED_ADD_LARGE_INTGR(
  491. &pPortDesc->pd_PortStats.prtst_NbpPacketInProcessTime,
  492. TimeD,
  493. &AtalkStatsLock.SpinLock);
  494. INTERLOCKED_INCREMENT_LONG_DPC(
  495. &pPortDesc->pd_PortStats.prtst_NumNbpPacketsIn,
  496. &AtalkStatsLock.SpinLock);
  497. }
  498. /*** atalkNbpTimer
  499. *
  500. */
  501. LOCAL LONG FASTCALL
  502. atalkNbpTimer(
  503. IN PTIMERLIST pTimer,
  504. IN BOOLEAN TimerShuttingDown
  505. )
  506. {
  507. PPEND_NAME pCurrPendName;
  508. ATALK_ERROR error;
  509. PDDP_ADDROBJ pDdpAddr;
  510. BOOLEAN RestartTimer = TRUE;
  511. BYTE Reason;
  512. pCurrPendName = (PPEND_NAME)CONTAINING_RECORD(pTimer, PEND_NAME, pdn_Timer);
  513. ASSERT (VALID_PENDNAME(pCurrPendName));
  514. Reason = pCurrPendName->pdn_Reason;
  515. ASSERT ((Reason == FOR_REGISTER) ||
  516. (Reason == FOR_LOOKUP) ||
  517. (Reason == FOR_CONFIRM));
  518. pDdpAddr = pCurrPendName->pdn_pDdpAddr;
  519. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  520. ("atalkNbpTimer: For Socket %lx, PendName %lx\n",
  521. pDdpAddr, pCurrPendName));
  522. ACQUIRE_SPIN_LOCK_DPC(&pCurrPendName->pdn_Lock);
  523. if (TimerShuttingDown ||
  524. (pCurrPendName->pdn_Flags & PDN_CLOSING))
  525. pCurrPendName->pdn_RemainingBroadcasts = 1;
  526. if (--(pCurrPendName->pdn_RemainingBroadcasts) == 0)
  527. {
  528. RestartTimer = FALSE;
  529. if (Reason == FOR_REGISTER)
  530. {
  531. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  532. ("atalkNbpTimer: Register success\n"));
  533. ACQUIRE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  534. pCurrPendName->pdn_pRegdName->rdn_Next = pDdpAddr->ddpao_RegNames;
  535. pDdpAddr->ddpao_RegNames = pCurrPendName->pdn_pRegdName;
  536. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  537. pCurrPendName->pdn_Flags &= ~PDN_FREE_REGDNAME;
  538. }
  539. pCurrPendName->pdn_Flags |= PDN_CLOSING;
  540. }
  541. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  542. ("atalkNbpTimer: Remaining broadcasts %d\n",
  543. pCurrPendName->pdn_RemainingBroadcasts));
  544. if (RestartTimer)
  545. {
  546. pCurrPendName->pdn_RefCount ++;
  547. RELEASE_SPIN_LOCK_DPC(&pCurrPendName->pdn_Lock);
  548. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  549. ("atalkNbpTimer: Sending another request\n"));
  550. if (!atalkNbpSendRequest(pCurrPendName))
  551. {
  552. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_ERR,
  553. ("atalkNbpTimer: atalkNbpSendRequest failed\n"));
  554. }
  555. }
  556. else
  557. {
  558. RELEASE_SPIN_LOCK_DPC(&pCurrPendName->pdn_Lock);
  559. error = ATALK_NO_ERROR;
  560. if (Reason == FOR_CONFIRM)
  561. {
  562. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  563. ("atalkNbpTimer: Confirm Failure\n"));
  564. error = ATALK_TIMEOUT;
  565. }
  566. else if (Reason == FOR_LOOKUP)
  567. {
  568. ((PNBP_LOOKUP_PARAMS)(pCurrPendName->pdn_pActReq->ar_pParms))->NoTuplesRead =
  569. pCurrPendName->pdn_TotalTuples;
  570. }
  571. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  572. ("atalkNbpTimer: Calling completion routine\n"));
  573. pCurrPendName->pdn_Status = error;
  574. atalkNbpDerefPendName(pCurrPendName); // Take away creation reference
  575. }
  576. atalkNbpDerefPendName(pCurrPendName);
  577. return (RestartTimer ? ATALK_TIMER_REQUEUE : ATALK_TIMER_NO_REQUEUE);
  578. }
  579. /*** atalkNbpLookupNames
  580. *
  581. */
  582. LOCAL VOID
  583. atalkNbpLookupNames(
  584. IN PPORT_DESCRIPTOR pPortDesc,
  585. IN PDDP_ADDROBJ pDdpAddr,
  586. IN PNBPTUPLE pNbpTuple,
  587. IN SHORT NbpId
  588. )
  589. {
  590. int i, index, TupleCnt;
  591. BOOLEAN AllocNewBuffDesc = TRUE;
  592. PBUFFER_DESC pBuffDesc,
  593. pBuffDescStart = NULL,
  594. *ppBuffDesc = &pBuffDescStart;
  595. PATALK_NODE pNode = pDdpAddr->ddpao_Node;
  596. SEND_COMPL_INFO SendInfo;
  597. PBYTE Datagram;
  598. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  599. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  600. ("atalkNbpLookupNames: Entered\n"));
  601. // Does the requestor atleast has the right zone ?
  602. if ((pNbpTuple->tpl_Zone[0] != '*') ||
  603. (pNbpTuple->tpl_ZoneLen != 1))
  604. {
  605. // If either we do not know our zone or if it does not match or
  606. // we are an extended network, return - we have nothing to do
  607. if (EXT_NET(pPortDesc))
  608. {
  609. if (!(pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE) ||
  610. ((pPortDesc->pd_DesiredZone == NULL) ?1:
  611. (!AtalkFixedCompareCaseInsensitive(pNbpTuple->tpl_Zone,
  612. pNbpTuple->tpl_ZoneLen,
  613. pPortDesc->pd_DesiredZone->zn_Zone,
  614. pPortDesc->pd_DesiredZone->zn_ZoneLen))))
  615. {
  616. return;
  617. }
  618. }
  619. }
  620. // Walk the registered names list on all sockets open on this node and
  621. // see if we have a matching name. We have to walk the pending names
  622. // list also (should not answer, if we the node trying to register the
  623. // name).
  624. ACQUIRE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Node->an_Lock);
  625. for (i = 0; i < NODE_DDPAO_HASH_SIZE; i++)
  626. {
  627. PDDP_ADDROBJ pSkt;
  628. for (pSkt = pNode->an_DdpAoHash[i];
  629. pSkt != NULL;
  630. pSkt = pSkt->ddpao_Next)
  631. {
  632. PREGD_NAME pRegdName;
  633. PPEND_NAME pPendName;
  634. ACQUIRE_SPIN_LOCK_DPC(&pSkt->ddpao_Lock);
  635. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  636. ("atalkNbpLookupNames: Checking Socket %lx\n", pSkt));
  637. // First check registered names
  638. for (pRegdName = pSkt->ddpao_RegNames;
  639. pRegdName != NULL;
  640. pRegdName = pRegdName->rdn_Next)
  641. {
  642. ASSERT (VALID_REGDNAME(pRegdName));
  643. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  644. ("atalkNbpLookupNames: Checking RegdName %lx\n", pRegdName));
  645. if (!atalkNbpMatchWild(pNbpTuple->tpl_Object,
  646. pNbpTuple->tpl_ObjectLen,
  647. pRegdName->rdn_Tuple.tpl_Object,
  648. pRegdName->rdn_Tuple.tpl_ObjectLen) ||
  649. !atalkNbpMatchWild(pNbpTuple->tpl_Type,
  650. pNbpTuple->tpl_TypeLen,
  651. pRegdName->rdn_Tuple.tpl_Type,
  652. pRegdName->rdn_Tuple.tpl_TypeLen))
  653. continue;
  654. // Allocate a new buffer descriptor, if we must
  655. if (AllocNewBuffDesc)
  656. {
  657. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  658. MAX_DGRAM_SIZE,
  659. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  660. break;
  661. Datagram = pBuffDesc->bd_CharBuffer;
  662. index = sizeof(NBPHDR);
  663. TupleCnt = 0;
  664. *ppBuffDesc = pBuffDesc;
  665. pBuffDesc->bd_Next = NULL;
  666. ppBuffDesc = &pBuffDesc->bd_Next;
  667. AllocNewBuffDesc = FALSE;
  668. }
  669. // We have a match. Build complete Nbp tuple
  670. index += atalkNbpEncodeTuple(&pRegdName->rdn_Tuple,
  671. "*",
  672. 1,
  673. 0,
  674. Datagram+index);
  675. TupleCnt ++;
  676. if (((index + MAX_NBP_TUPLELENGTH) > MAX_DGRAM_SIZE) ||
  677. (TupleCnt == 0x0F))
  678. {
  679. ((PNBPHDR)Datagram)->_NbpId = (BYTE)NbpId;
  680. ((PNBPHDR)Datagram)->_CmdAndTupleCnt =
  681. (NBP_LOOKUP_REPLY << 4) + TupleCnt;
  682. AllocNewBuffDesc = TRUE;
  683. pBuffDesc->bd_Length = (SHORT)index;
  684. }
  685. }
  686. // Now check pending names
  687. for (pPendName = pSkt->ddpao_PendNames;
  688. pPendName != NULL;
  689. pPendName = pPendName->pdn_Next)
  690. {
  691. ASSERT (VALID_PENDNAME(pPendName));
  692. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  693. ("atalkNbpLookupNames: Checking PendName %lx\n", pPendName));
  694. // Ignore all but the ones that are being registered
  695. if (pPendName->pdn_Reason != FOR_REGISTER)
  696. continue;
  697. // Also those that we are registering
  698. if ((pSkt->ddpao_Node->an_NodeAddr.atn_Network ==
  699. pNbpTuple->tpl_Address.ata_Network) &&
  700. (pSkt->ddpao_Node->an_NodeAddr.atn_Node ==
  701. pNbpTuple->tpl_Address.ata_Node) &&
  702. (pPendName->pdn_NbpId == (BYTE)NbpId))
  703. continue;
  704. if ((pPendName->pdn_pRegdName == NULL) ||
  705. !atalkNbpMatchWild(
  706. pNbpTuple->tpl_Object,
  707. pNbpTuple->tpl_ObjectLen,
  708. pPendName->pdn_pRegdName->rdn_Tuple.tpl_Object,
  709. pPendName->pdn_pRegdName->rdn_Tuple.tpl_ObjectLen) ||
  710. !atalkNbpMatchWild(
  711. pNbpTuple->tpl_Type,
  712. pNbpTuple->tpl_TypeLen,
  713. pPendName->pdn_pRegdName->rdn_Tuple.tpl_Type,
  714. pPendName->pdn_pRegdName->rdn_Tuple.tpl_TypeLen))
  715. {
  716. continue;
  717. }
  718. // Allocate a new buffer descriptor, if we must
  719. if (AllocNewBuffDesc)
  720. {
  721. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  722. MAX_DGRAM_SIZE,
  723. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  724. break;
  725. Datagram = pBuffDesc->bd_CharBuffer;
  726. index = sizeof(NBPHDR);
  727. TupleCnt = 0;
  728. *ppBuffDesc = pBuffDesc;
  729. pBuffDesc->bd_Next = NULL;
  730. ppBuffDesc = &pBuffDesc->bd_Next;
  731. AllocNewBuffDesc = FALSE;
  732. }
  733. // We have a match. Build complete Nbp tuple
  734. index += atalkNbpEncodeTuple(&pPendName->pdn_pRegdName->rdn_Tuple,
  735. "*",
  736. 1,
  737. 0,
  738. Datagram+index);
  739. TupleCnt ++;
  740. if (((index + MAX_NBP_TUPLELENGTH) > MAX_DGRAM_SIZE) ||
  741. (TupleCnt == 0x0F))
  742. {
  743. ((PNBPHDR)Datagram)->_NbpId = (BYTE)NbpId;
  744. ((PNBPHDR)Datagram)->_CmdAndTupleCnt =
  745. (NBP_LOOKUP_REPLY << 4) + TupleCnt;
  746. AllocNewBuffDesc = TRUE;
  747. pBuffDesc->bd_Length = (SHORT)index;
  748. }
  749. }
  750. RELEASE_SPIN_LOCK_DPC(&pSkt->ddpao_Lock);
  751. }
  752. }
  753. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Node->an_Lock);
  754. // Close the current buffdesc
  755. if (!AllocNewBuffDesc)
  756. {
  757. ((PNBPHDR)Datagram)->_NbpId = (BYTE)NbpId;
  758. ((PNBPHDR)Datagram)->_CmdAndTupleCnt = (NBP_LOOKUP_REPLY << 4) + TupleCnt;
  759. pBuffDesc->bd_Length = (SHORT)index;
  760. }
  761. // Now blast off all the datagrams that we have filled up
  762. SendInfo.sc_TransmitCompletion = atalkNbpSendComplete;
  763. // SendInfo.sc_Ctx2 = NULL;
  764. // SendInfo.sc_Ctx3 = NULL;
  765. for (pBuffDesc = pBuffDescStart;
  766. pBuffDesc != NULL;
  767. pBuffDesc = pBuffDescStart)
  768. {
  769. ATALK_ERROR ErrorCode;
  770. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  771. ("atalkNbpLookupNames: Sending lookup response\n"));
  772. pBuffDescStart = pBuffDesc->bd_Next;
  773. pBuffDesc->bd_Next = NULL;
  774. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  775. ("atalkNbpLookupNames: Sending %lx\n", pBuffDesc));
  776. ASSERT(pBuffDesc->bd_Length > 0);
  777. // Length is already properly set in the buffer descriptor.
  778. SendInfo.sc_Ctx1 = pBuffDesc;
  779. ErrorCode = AtalkDdpSend(pDdpAddr,
  780. &pNbpTuple->tpl_Address,
  781. DDPPROTO_NBP,
  782. FALSE,
  783. pBuffDesc,
  784. NULL,
  785. 0,
  786. NULL,
  787. &SendInfo);
  788. if (!ATALK_SUCCESS(ErrorCode))
  789. {
  790. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_WARN,
  791. ("atalkNbpLookupNames: DdpSend failed %ld\n", ErrorCode));
  792. AtalkFreeBuffDesc(pBuffDesc);
  793. }
  794. }
  795. }
  796. /*** AtalkNbpAction
  797. *
  798. */
  799. ATALK_ERROR
  800. AtalkNbpAction(
  801. IN PDDP_ADDROBJ pDdpAddr,
  802. IN BYTE Reason,
  803. IN PNBPTUPLE pNbpTuple,
  804. OUT PAMDL pAMdl OPTIONAL, // FOR_LOOKUP
  805. IN USHORT MaxTuples OPTIONAL, // FOR_LOOKUP
  806. IN PACTREQ pActReq
  807. )
  808. {
  809. PPORT_DESCRIPTOR pPortDesc;
  810. PPEND_NAME pPendName = NULL;
  811. PREGD_NAME pRegdName = NULL;
  812. ATALK_ERROR Status = ATALK_INVALID_PARAMETER;
  813. LONG MdlLen = 0;
  814. BOOLEAN DefZone = FALSE;
  815. ASSERT (Reason == FOR_REGISTER ||
  816. Reason == FOR_CONFIRM ||
  817. Reason == FOR_LOOKUP);
  818. do
  819. {
  820. if ((pNbpTuple->tpl_ObjectLen == 0) ||
  821. (pNbpTuple->tpl_ObjectLen > MAX_ENTITY_LENGTH) ||
  822. (pNbpTuple->tpl_TypeLen == 0) ||
  823. (pNbpTuple->tpl_TypeLen > MAX_ENTITY_LENGTH))
  824. break;
  825. if ((Reason == FOR_LOOKUP) &&
  826. ((pAMdl == NULL) ||
  827. ((MdlLen = AtalkSizeMdlChain(pAMdl)) < sizeof(NBPTUPLE))))
  828. {
  829. Status = ATALK_BUFFER_TOO_SMALL;
  830. break;
  831. }
  832. pPortDesc = pDdpAddr->ddpao_Node->an_Port;
  833. if (pNbpTuple->tpl_ZoneLen != 0)
  834. {
  835. if (pNbpTuple->tpl_ZoneLen > MAX_ENTITY_LENGTH)
  836. break;
  837. if (((pNbpTuple->tpl_Zone[0] == '*') && (pNbpTuple->tpl_ZoneLen == 1)) ||
  838. ((pPortDesc->pd_DesiredZone != NULL) &&
  839. AtalkFixedCompareCaseInsensitive(pNbpTuple->tpl_Zone,
  840. pNbpTuple->tpl_ZoneLen,
  841. pPortDesc->pd_DesiredZone->zn_Zone,
  842. pPortDesc->pd_DesiredZone->zn_ZoneLen)))
  843. {
  844. DefZone = TRUE;
  845. }
  846. }
  847. else
  848. {
  849. pNbpTuple->tpl_Zone[0] = '*';
  850. pNbpTuple->tpl_ZoneLen = 1;
  851. DefZone = TRUE;
  852. }
  853. if (Reason != FOR_LOOKUP) // i.e. REGISTER or CONFIRM
  854. {
  855. if ((pNbpTuple->tpl_Object[0] == '=') ||
  856. (pNbpTuple->tpl_Type[0] == '=') ||
  857. (AtalkSearchBuf(pNbpTuple->tpl_Object,
  858. pNbpTuple->tpl_ObjectLen,
  859. NBP_WILD_CHARACTER) != NULL) ||
  860. (AtalkSearchBuf(pNbpTuple->tpl_Type,
  861. pNbpTuple->tpl_TypeLen,
  862. NBP_WILD_CHARACTER) != NULL))
  863. break;
  864. if ((Reason == FOR_REGISTER) && !DefZone)
  865. break;
  866. }
  867. // For extended networks, set the zone name correctly
  868. if (DefZone &&
  869. (pPortDesc->pd_Flags & (PD_EXT_NET | PD_VALID_DESIRED_ZONE)) ==
  870. (PD_EXT_NET | PD_VALID_DESIRED_ZONE))
  871. {
  872. RtlCopyMemory(pNbpTuple->tpl_Zone,
  873. pPortDesc->pd_DesiredZone->zn_Zone,
  874. pPortDesc->pd_DesiredZone->zn_ZoneLen);
  875. pNbpTuple->tpl_ZoneLen = pPortDesc->pd_DesiredZone->zn_ZoneLen;
  876. }
  877. // Start by building the pending name structure. This needs to be linked
  878. // to the socket holding the spin lock and getting a unique enumerator
  879. // and an nbp id. If either of these fail, then we undo the stuff.
  880. if (((pPendName = (PPEND_NAME)AtalkAllocZeroedMemory(sizeof(PEND_NAME))) == NULL) ||
  881. ((pRegdName = (PREGD_NAME)AtalkAllocZeroedMemory(sizeof(REGD_NAME))) == NULL))
  882. {
  883. if (pPendName != NULL)
  884. {
  885. AtalkFreeMemory(pPendName);
  886. pPendName = NULL;
  887. }
  888. Status = ATALK_RESR_MEM;
  889. break;
  890. }
  891. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  892. ("AtalkNbpAction: %s, Socket %lx, PendName %lx, RegdName %lx\n",
  893. (Reason == FOR_REGISTER) ? "Register" :
  894. ((Reason == FOR_CONFIRM) ? "Confirm" : "Lookup"),
  895. pDdpAddr, pPendName, pRegdName));
  896. #if DBG
  897. pRegdName->rdn_Signature = RDN_SIGNATURE;
  898. pPendName->pdn_Signature = PDN_SIGNATURE;
  899. #endif
  900. pRegdName->rdn_Tuple.tpl_ObjectLen = pNbpTuple->tpl_ObjectLen;;
  901. RtlCopyMemory(pRegdName->rdn_Tuple.tpl_Object,
  902. pNbpTuple->tpl_Object,
  903. pNbpTuple->tpl_ObjectLen);
  904. pRegdName->rdn_Tuple.tpl_TypeLen = pNbpTuple->tpl_TypeLen;;
  905. RtlCopyMemory(pRegdName->rdn_Tuple.tpl_Type,
  906. pNbpTuple->tpl_Type,
  907. pNbpTuple->tpl_TypeLen);
  908. pRegdName->rdn_Tuple.tpl_ZoneLen = pNbpTuple->tpl_ZoneLen;;
  909. RtlCopyMemory(pRegdName->rdn_Tuple.tpl_Zone,
  910. pNbpTuple->tpl_Zone,
  911. pNbpTuple->tpl_ZoneLen);
  912. pRegdName->rdn_Tuple.tpl_Address.ata_Address = pDdpAddr->ddpao_Addr.ata_Address;
  913. pPendName->pdn_pRegdName = pRegdName;
  914. INITIALIZE_SPIN_LOCK(&pPendName->pdn_Lock);
  915. pPendName->pdn_RefCount = 3; // Reference for creation, timer & for ourselves
  916. pPendName->pdn_pDdpAddr = pDdpAddr;
  917. AtalkDdpReferenceByPtr(pDdpAddr, &Status);
  918. ASSERT(ATALK_SUCCESS(Status));
  919. pPendName->pdn_Flags = PDN_FREE_REGDNAME;
  920. pPendName->pdn_Reason = Reason;
  921. pPendName->pdn_pActReq = pActReq;
  922. pPendName->pdn_RemainingBroadcasts = NBP_NUM_BROADCASTS;
  923. AtalkTimerInitialize(&pPendName->pdn_Timer,
  924. atalkNbpTimer,
  925. NBP_BROADCAST_INTERVAL);
  926. if (Reason == FOR_CONFIRM)
  927. pPendName->pdn_ConfirmAddr = pNbpTuple->tpl_Address;
  928. else if (Reason == FOR_LOOKUP)
  929. {
  930. pPendName->pdn_pAMdl = pAMdl;
  931. pPendName->pdn_MdlLength = (USHORT)MdlLen;
  932. pPendName->pdn_TotalTuples = 0;
  933. pPendName->pdn_MaxTuples = MaxTuples;
  934. // If we are not doing a wild card search, restrict
  935. // the tuples to one so we get out early instead of
  936. // the max. time-out since we are never going to
  937. // fill the buffer
  938. if (!((pNbpTuple->tpl_Object[0] == '=') ||
  939. (pNbpTuple->tpl_Type[0] == '=') ||
  940. (pNbpTuple->tpl_Zone[0] == '=') ||
  941. (AtalkSearchBuf(pNbpTuple->tpl_Object,
  942. pNbpTuple->tpl_ObjectLen,
  943. NBP_WILD_CHARACTER) != NULL) ||
  944. (AtalkSearchBuf(pNbpTuple->tpl_Type,
  945. pNbpTuple->tpl_TypeLen,
  946. NBP_WILD_CHARACTER) != NULL) ||
  947. (AtalkSearchBuf(pNbpTuple->tpl_Zone,
  948. pNbpTuple->tpl_ZoneLen,
  949. NBP_WILD_CHARACTER) != NULL)))
  950. {
  951. pPendName->pdn_MaxTuples = 1;
  952. }
  953. }
  954. // We're going to send a directed lookup for confirms, or either a
  955. // broadcast request or a lookup for registers or lookup depending
  956. // on whether we know about a router or not. We do not have to bother
  957. // checking the registered names list, for register, in our node
  958. // because the broadcast will eventually get to us and we'll handle
  959. // it then ! Request packet, with one tuple
  960. if (Reason == FOR_CONFIRM) // Send to confirming node
  961. ((PNBPHDR)(pPendName->pdn_Datagram))->_CmdAndTupleCnt =
  962. (NBP_LOOKUP << 4) + 1;
  963. else if (pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  964. ((PNBPHDR)(pPendName->pdn_Datagram))->_CmdAndTupleCnt =
  965. (NBP_BROADCAST_REQUEST << 4) + 1;
  966. else ((PNBPHDR)(pPendName->pdn_Datagram))->_CmdAndTupleCnt =
  967. (NBP_LOOKUP << 4) + 1;
  968. pPendName->pdn_DatagramLength = sizeof(NBPHDR) +
  969. atalkNbpEncodeTuple(&pPendName->pdn_pRegdName->rdn_Tuple,
  970. NULL,
  971. 0,
  972. // NAMESINFORMATION_SOCKET,
  973. LAST_DYNAMIC_SOCKET,
  974. pPendName->pdn_Datagram + sizeof(NBPHDR));
  975. // Alloc an Nbp Id and an enumerator and link it into the list
  976. atalkNbpLinkPendingNameInList(pDdpAddr, pPendName);
  977. ((PNBPHDR)(pPendName->pdn_Datagram))->_NbpId = (BYTE)(pPendName->pdn_NbpId);
  978. AtalkTimerScheduleEvent(&pPendName->pdn_Timer);
  979. atalkNbpSendRequest(pPendName);
  980. atalkNbpDerefPendName(pPendName); // We are done now.
  981. Status = ATALK_PENDING;
  982. } while (FALSE);
  983. return Status;
  984. }
  985. /*** AtalkNbpRemove
  986. *
  987. */
  988. ATALK_ERROR
  989. AtalkNbpRemove(
  990. IN PDDP_ADDROBJ pDdpAddr,
  991. IN PNBPTUPLE pNbpTuple,
  992. IN PACTREQ pActReq
  993. )
  994. {
  995. PREGD_NAME pRegdName, *ppRegdName;
  996. KIRQL OldIrql;
  997. ATALK_ERROR Status = ATALK_INVALID_PARAMETER;
  998. do
  999. {
  1000. // Remove a registered NBP name. Zone must either be NULL or "*"
  1001. if ((pNbpTuple->tpl_ObjectLen == 0) ||
  1002. (pNbpTuple->tpl_ObjectLen > MAX_ENTITY_LENGTH) ||
  1003. (pNbpTuple->tpl_TypeLen == 0) ||
  1004. (pNbpTuple->tpl_TypeLen > MAX_ENTITY_LENGTH))
  1005. break;
  1006. if (pNbpTuple->tpl_ZoneLen == 0)
  1007. {
  1008. pNbpTuple->tpl_ZoneLen = 1;
  1009. pNbpTuple->tpl_Zone[0] = '*';
  1010. }
  1011. else
  1012. {
  1013. if ((pNbpTuple->tpl_ZoneLen != 1) ||
  1014. (pNbpTuple->tpl_Zone[0] != '*'))
  1015. break;
  1016. }
  1017. if ((pNbpTuple->tpl_Object[0] == '=') || (pNbpTuple->tpl_Type[0] == '=') ||
  1018. AtalkSearchBuf(pNbpTuple->tpl_Object, pNbpTuple->tpl_ObjectLen, NBP_WILD_CHARACTER) ||
  1019. AtalkSearchBuf(pNbpTuple->tpl_Type, pNbpTuple->tpl_TypeLen, NBP_WILD_CHARACTER))
  1020. break;
  1021. // Search in the registered names list in the open socket
  1022. // Lock down the structure first
  1023. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  1024. for (ppRegdName = &pDdpAddr->ddpao_RegNames;
  1025. (pRegdName = *ppRegdName) != NULL;
  1026. ppRegdName = &pRegdName->rdn_Next)
  1027. {
  1028. ASSERT (VALID_REGDNAME(pRegdName));
  1029. if (AtalkFixedCompareCaseInsensitive(pNbpTuple->tpl_Object,
  1030. pNbpTuple->tpl_ObjectLen,
  1031. pRegdName->rdn_Tuple.tpl_Object,
  1032. pRegdName->rdn_Tuple.tpl_ObjectLen) &&
  1033. AtalkFixedCompareCaseInsensitive(pNbpTuple->tpl_Type,
  1034. pNbpTuple->tpl_TypeLen,
  1035. pRegdName->rdn_Tuple.tpl_Type,
  1036. pRegdName->rdn_Tuple.tpl_TypeLen))
  1037. {
  1038. *ppRegdName = pRegdName->rdn_Next;
  1039. break;
  1040. }
  1041. }
  1042. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  1043. Status = ATALK_FAILURE;
  1044. if (pRegdName != NULL)
  1045. {
  1046. AtalkFreeMemory(pRegdName);
  1047. Status = ATALK_NO_ERROR;
  1048. }
  1049. } while (FALSE);
  1050. AtalkUnlockNbpIfNecessary();
  1051. (*pActReq->ar_Completion)(Status, pActReq);
  1052. return (ATALK_PENDING);
  1053. }
  1054. /*** atalkNbpMatchWild
  1055. *
  1056. */
  1057. LOCAL BOOLEAN
  1058. atalkNbpMatchWild(
  1059. IN PBYTE WildString,
  1060. IN BYTE WildStringLen,
  1061. IN PBYTE String,
  1062. IN BYTE StringLen
  1063. )
  1064. /*++
  1065. There are two kinds of wild card searches. An '=' by itself matches anything.
  1066. Partial matches use the 'curly equals' or 0xC5. So representing that by the
  1067. '=' character below.
  1068. foo= will match any name which starts with foo.
  1069. =foo will match any name which ends in foo.
  1070. =foo= will match any name with foo in it.
  1071. foo=bar will match any name that starts with foo and ends with bar.
  1072. --*/
  1073. {
  1074. PBYTE pTarget, pTokStr;
  1075. int TargetLen, TokStrLen;
  1076. PBYTE pWildCard, pCurStr, pCurWild;
  1077. int Len;
  1078. int i;
  1079. BOOLEAN fWildCharPresent = FALSE;
  1080. // first see if it's a 'match any' request
  1081. if ((WildString[0] == 0) ||
  1082. ((WildString[0] == '=') && (WildStringLen == 1)))
  1083. return TRUE;
  1084. // now, check to see if there is any wild char in the requested name
  1085. for (i=0; i<WildStringLen; i++)
  1086. {
  1087. if (WildString[i] == NBP_WILD_CHARACTER)
  1088. {
  1089. fWildCharPresent = TRUE;
  1090. break;
  1091. }
  1092. }
  1093. // if there is no wild character in the requested name, this is
  1094. // a straight forward string compare!
  1095. if (!fWildCharPresent)
  1096. {
  1097. if (WildStringLen != StringLen)
  1098. return FALSE;
  1099. if (SubStringMatch(WildString,String,StringLen,WildStringLen))
  1100. return TRUE;
  1101. else
  1102. return FALSE;
  1103. }
  1104. // ok, now deal with the wild character mess
  1105. pTarget = String;
  1106. pTokStr = WildString;
  1107. TargetLen = StringLen;
  1108. while (WildStringLen > 0 && StringLen > 0)
  1109. {
  1110. // find length of substring until the next wild-char
  1111. TokStrLen = GetTokenLen(pTokStr,WildStringLen,NBP_WILD_CHARACTER);
  1112. if (TokStrLen > 0)
  1113. {
  1114. if (!SubStringMatch(pTarget,pTokStr,StringLen,TokStrLen))
  1115. {
  1116. return (FALSE);
  1117. }
  1118. pTokStr += TokStrLen;
  1119. WildStringLen -= (BYTE)TokStrLen;
  1120. pTarget += TokStrLen;
  1121. StringLen -= (BYTE)TokStrLen;
  1122. }
  1123. // the very first char was wild-char: skip over it
  1124. else
  1125. {
  1126. pTokStr++;
  1127. WildStringLen--;
  1128. }
  1129. }
  1130. // if we survived all the checks, this string is a match!
  1131. return (TRUE);
  1132. }
  1133. /*** atalkNbpEncodeTuple
  1134. *
  1135. */
  1136. LOCAL SHORT
  1137. atalkNbpEncodeTuple(
  1138. IN PNBPTUPLE pNbpTuple,
  1139. IN PBYTE pZone OPTIONAL, // Override zone
  1140. IN BYTE ZoneLen OPTIONAL, // Valid only if pZone != NULL
  1141. IN BYTE Socket OPTIONAL,
  1142. OUT PBYTE pBuffer
  1143. )
  1144. {
  1145. typedef struct
  1146. {
  1147. BYTE _NetNum[2];
  1148. BYTE _Node;
  1149. BYTE _Socket;
  1150. BYTE _Enumerator;
  1151. } HDR, *PHDR;
  1152. SHORT Len = sizeof(HDR);
  1153. if (pZone == NULL)
  1154. {
  1155. pZone = pNbpTuple->tpl_Zone;
  1156. ZoneLen = pNbpTuple->tpl_ZoneLen;
  1157. }
  1158. PUTSHORT2SHORT(((PHDR)pBuffer)->_NetNum, pNbpTuple->tpl_Address.ata_Network);
  1159. ((PHDR)pBuffer)->_Node = pNbpTuple->tpl_Address.ata_Node;
  1160. ((PHDR)pBuffer)->_Socket = pNbpTuple->tpl_Address.ata_Socket;
  1161. if (Socket != 0)
  1162. ((PHDR)pBuffer)->_Socket = Socket;
  1163. PUTSHORT2BYTE(&((PHDR)pBuffer)->_Enumerator, pNbpTuple->tpl_Enumerator);
  1164. pBuffer += sizeof(HDR);
  1165. *pBuffer++ = pNbpTuple->tpl_ObjectLen;
  1166. RtlCopyMemory(pBuffer, pNbpTuple->tpl_Object, pNbpTuple->tpl_ObjectLen);
  1167. pBuffer += pNbpTuple->tpl_ObjectLen;
  1168. Len += (pNbpTuple->tpl_ObjectLen + 1);
  1169. *pBuffer++ = pNbpTuple->tpl_TypeLen;
  1170. RtlCopyMemory(pBuffer, pNbpTuple->tpl_Type, pNbpTuple->tpl_TypeLen);
  1171. pBuffer += pNbpTuple->tpl_TypeLen;
  1172. Len += (pNbpTuple->tpl_TypeLen + 1);
  1173. *pBuffer++ = ZoneLen;
  1174. RtlCopyMemory(pBuffer, pZone, ZoneLen);
  1175. // pBuffer += ZoneLen;
  1176. Len += (ZoneLen + 1);
  1177. return (Len);
  1178. }
  1179. /*** atalkNbpDecodeTuple
  1180. *
  1181. */
  1182. LOCAL SHORT
  1183. atalkNbpDecodeTuple(
  1184. IN PBYTE pBuffer,
  1185. IN USHORT PktLen,
  1186. OUT PNBPTUPLE pNbpTuple
  1187. )
  1188. {
  1189. typedef struct
  1190. {
  1191. BYTE _NetNum[2];
  1192. BYTE _Node;
  1193. BYTE _Socket;
  1194. BYTE _Enumerator;
  1195. } HDR, *PHDR;
  1196. SHORT Len = 0;
  1197. do
  1198. {
  1199. if (PktLen < MIN_NBP_TUPLELENGTH)
  1200. {
  1201. break;
  1202. }
  1203. GETSHORT2SHORT(&pNbpTuple->tpl_Address.ata_Network,
  1204. ((PHDR)pBuffer)->_NetNum);
  1205. pNbpTuple->tpl_Address.ata_Node = ((PHDR)pBuffer)->_Node;
  1206. pNbpTuple->tpl_Address.ata_Socket = ((PHDR)pBuffer)->_Socket;
  1207. GETBYTE2SHORT(&pNbpTuple->tpl_Enumerator,
  1208. &((PHDR)pBuffer)->_Enumerator);
  1209. // Get past the header
  1210. pBuffer += sizeof(HDR);
  1211. PktLen -= sizeof(HDR);
  1212. Len = sizeof(HDR);
  1213. pNbpTuple->tpl_ObjectLen = *pBuffer++;
  1214. PktLen --;
  1215. if ((pNbpTuple->tpl_ObjectLen > PktLen) ||
  1216. (pNbpTuple->tpl_ObjectLen > MAX_ENTITY_LENGTH))
  1217. {
  1218. Len = 0;
  1219. break;
  1220. }
  1221. RtlCopyMemory(pNbpTuple->tpl_Object, pBuffer, pNbpTuple->tpl_ObjectLen);
  1222. pBuffer += pNbpTuple->tpl_ObjectLen;
  1223. PktLen -= pNbpTuple->tpl_ObjectLen;
  1224. Len += (pNbpTuple->tpl_ObjectLen + 1);
  1225. if (PktLen == 0)
  1226. {
  1227. Len = 0;
  1228. break;
  1229. }
  1230. pNbpTuple->tpl_TypeLen = *pBuffer++;
  1231. PktLen --;
  1232. if ((pNbpTuple->tpl_TypeLen > PktLen) ||
  1233. (pNbpTuple->tpl_TypeLen > MAX_ENTITY_LENGTH))
  1234. {
  1235. Len = 0;
  1236. break;
  1237. }
  1238. RtlCopyMemory(pNbpTuple->tpl_Type, pBuffer, pNbpTuple->tpl_TypeLen);
  1239. pBuffer += pNbpTuple->tpl_TypeLen;
  1240. PktLen -= pNbpTuple->tpl_TypeLen;
  1241. Len += (pNbpTuple->tpl_TypeLen + 1);
  1242. if (PktLen == 0)
  1243. {
  1244. Len = 0;
  1245. break;
  1246. }
  1247. pNbpTuple->tpl_ZoneLen = *pBuffer++;
  1248. PktLen --;
  1249. if ((pNbpTuple->tpl_ZoneLen > PktLen) ||
  1250. (pNbpTuple->tpl_ZoneLen > MAX_ENTITY_LENGTH))
  1251. {
  1252. Len = 0;
  1253. break;
  1254. }
  1255. RtlCopyMemory(pNbpTuple->tpl_Zone, pBuffer, pNbpTuple->tpl_ZoneLen);
  1256. Len += (pNbpTuple->tpl_ZoneLen + 1);
  1257. } while (FALSE);
  1258. return (Len);
  1259. }
  1260. /*** atalkNbpLinkPendingNameInList
  1261. *
  1262. */
  1263. LOCAL VOID
  1264. atalkNbpLinkPendingNameInList(
  1265. IN PDDP_ADDROBJ pDdpAddr,
  1266. IN OUT PPEND_NAME pPendName
  1267. )
  1268. {
  1269. PATALK_NODE pNode = pDdpAddr->ddpao_Node;
  1270. KIRQL OldIrql;
  1271. ASSERT (VALID_PENDNAME(pPendName));
  1272. ACQUIRE_SPIN_LOCK(&pNode->an_Lock, &OldIrql);
  1273. // Use the next consecutive values. If there are > 256 pending names on a node, we'll
  1274. // end up re-using the ids and enums. Still ok unless all of them are of the form
  1275. // =:=@=. Well lets just keep it simple.
  1276. pPendName->pdn_NbpId = ++(pNode->an_NextNbpId);
  1277. pPendName->pdn_pRegdName->rdn_Tuple.tpl_Enumerator = ++(pNode->an_NextNbpEnum);
  1278. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  1279. ("atalkNbpLinkPendingNameInList: Linking PendingName %lx in socket %lx\n",
  1280. pPendName, pDdpAddr));
  1281. pPendName->pdn_Next = pDdpAddr->ddpao_PendNames;
  1282. pDdpAddr->ddpao_PendNames = pPendName;
  1283. RELEASE_SPIN_LOCK(&pNode->an_Lock, OldIrql);
  1284. }
  1285. /*** AtalkNbpCloseSocket
  1286. *
  1287. */
  1288. VOID
  1289. AtalkNbpCloseSocket(
  1290. IN PDDP_ADDROBJ pDdpAddr
  1291. )
  1292. {
  1293. PPEND_NAME pPendName, *ppPendName;
  1294. PREGD_NAME pRegdName, *ppRegdName;
  1295. KIRQL OldIrql;
  1296. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  1297. // Free the pending names from the open socket.
  1298. for (ppPendName = &pDdpAddr->ddpao_PendNames;
  1299. (pPendName = *ppPendName) != NULL;
  1300. NOTHING)
  1301. {
  1302. ASSERT (VALID_PENDNAME(pPendName));
  1303. if (pPendName->pdn_Flags & PDN_CLOSING)
  1304. {
  1305. ppPendName = &pPendName->pdn_Next;
  1306. continue;
  1307. }
  1308. pPendName->pdn_Flags |= PDN_CLOSING;
  1309. pPendName->pdn_Status = ATALK_SOCKET_CLOSED;
  1310. // Cancel outstanding timers on the pending names
  1311. if (AtalkTimerCancelEvent(&pPendName->pdn_Timer, NULL))
  1312. {
  1313. atalkNbpDerefPendName(pPendName);
  1314. }
  1315. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  1316. ASSERT (pPendName->pdn_RefCount > 0);
  1317. atalkNbpDerefPendName(pPendName);
  1318. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  1319. ppPendName = &pDdpAddr->ddpao_PendNames;
  1320. }
  1321. // Free the registered names from the open socket.
  1322. for (ppRegdName = &pDdpAddr->ddpao_RegNames;
  1323. (pRegdName = *ppRegdName) != NULL;
  1324. NOTHING)
  1325. {
  1326. ASSERT (VALID_REGDNAME(pRegdName));
  1327. *ppRegdName = pRegdName->rdn_Next;
  1328. AtalkFreeMemory(pRegdName);
  1329. }
  1330. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  1331. }
  1332. /*** atalkNbpSendRequest
  1333. *
  1334. */
  1335. LOCAL BOOLEAN
  1336. atalkNbpSendRequest(
  1337. IN PPEND_NAME pPendName
  1338. )
  1339. {
  1340. PDDP_ADDROBJ pDdpAddr;
  1341. PBUFFER_DESC pBuffDesc;
  1342. ATALK_ADDR DestAddr;
  1343. ATALK_ADDR SrcAddr;
  1344. ATALK_ERROR Status;
  1345. PPORT_DESCRIPTOR pPortDesc;
  1346. SEND_COMPL_INFO SendInfo;
  1347. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  1348. ("atalkNbpSendRequest: Sending request for PendName %lx\n", pPendName));
  1349. ASSERT(!(pPendName->pdn_Flags & PDN_CLOSING));
  1350. pPortDesc = pPendName->pdn_pDdpAddr->ddpao_Node->an_Port;
  1351. DestAddr.ata_Socket = NAMESINFORMATION_SOCKET;
  1352. if (pPendName->pdn_Reason == FOR_CONFIRM)
  1353. {
  1354. DestAddr.ata_Network = pPendName->pdn_ConfirmAddr.ata_Network;
  1355. DestAddr.ata_Node = pPendName->pdn_ConfirmAddr.ata_Node;
  1356. }
  1357. else
  1358. {
  1359. if (pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  1360. {
  1361. DestAddr.ata_Network = pPortDesc->pd_ARouter.atn_Network;
  1362. DestAddr.ata_Node = pPortDesc->pd_ARouter.atn_Node;
  1363. }
  1364. else
  1365. {
  1366. DestAddr.ata_Network = CABLEWIDE_BROADCAST_NETWORK;
  1367. DestAddr.ata_Node = ATALK_BROADCAST_NODE;
  1368. }
  1369. }
  1370. SrcAddr.ata_Address = pPendName->pdn_pDdpAddr->ddpao_Addr.ata_Address;
  1371. // SrcAddr.ata_Socket = NAMESINFORMATION_SOCKET;
  1372. SrcAddr.ata_Socket = LAST_DYNAMIC_SOCKET;
  1373. AtalkDdpReferenceByAddr(pPendName->pdn_pDdpAddr->ddpao_Node->an_Port,
  1374. &SrcAddr,
  1375. &pDdpAddr,
  1376. &Status);
  1377. if (!ATALK_SUCCESS(Status))
  1378. {
  1379. return FALSE;
  1380. }
  1381. if ((pBuffDesc = AtalkAllocBuffDesc(pPendName->pdn_Datagram,
  1382. pPendName->pdn_DatagramLength,
  1383. BD_CHAR_BUFFER)) == NULL)
  1384. {
  1385. AtalkDdpDereference(pDdpAddr);
  1386. return FALSE;
  1387. }
  1388. ASSERT(pBuffDesc->bd_Length == pPendName->pdn_DatagramLength);
  1389. ASSERT(pBuffDesc->bd_Length > 0);
  1390. SendInfo.sc_TransmitCompletion = atalkNbpSendComplete;
  1391. SendInfo.sc_Ctx1 = pBuffDesc;
  1392. // SendInfo.sc_Ctx2 = NULL;
  1393. // SendInfo.sc_Ctx3 = NULL;
  1394. Status = AtalkDdpSend(pDdpAddr,
  1395. &DestAddr,
  1396. DDPPROTO_NBP,
  1397. FALSE,
  1398. pBuffDesc,
  1399. NULL,
  1400. 0,
  1401. NULL,
  1402. &SendInfo);
  1403. if (!ATALK_SUCCESS(Status))
  1404. {
  1405. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_ERR,
  1406. ("atalkNbpSendRequest: AtalkDdpSend Failed %lx\n", Status));
  1407. AtalkFreeBuffDesc(pBuffDesc);
  1408. }
  1409. AtalkDdpDereference(pDdpAddr);
  1410. return (ATALK_SUCCESS(Status));
  1411. }
  1412. /*** atalkNbpSendLookupDatagram
  1413. *
  1414. */
  1415. LOCAL VOID
  1416. atalkNbpSendLookupDatagram(
  1417. IN PPORT_DESCRIPTOR pPortDesc,
  1418. IN PDDP_ADDROBJ pDdpAddr OPTIONAL,
  1419. IN SHORT NbpId,
  1420. IN PNBPTUPLE pNbpTuple
  1421. )
  1422. {
  1423. PBYTE Datagram = NULL;
  1424. BYTE MulticastAddr[ELAP_ADDR_LEN];
  1425. PBUFFER_DESC pBuffDesc = NULL;
  1426. BOOLEAN DerefDdp = FALSE;
  1427. ULONG Len;
  1428. ATALK_ADDR Dst, Src;
  1429. ATALK_ERROR Status;
  1430. SEND_COMPL_INFO SendInfo;
  1431. if (pDdpAddr == NULL)
  1432. {
  1433. Src.ata_Network = pPortDesc->pd_ARouter.atn_Network;
  1434. Src.ata_Node = pPortDesc->pd_ARouter.atn_Node;
  1435. Src.ata_Socket = NAMESINFORMATION_SOCKET;
  1436. AtalkDdpReferenceByAddr(pPortDesc, &Src, &pDdpAddr, &Status);
  1437. if (!ATALK_SUCCESS(Status))
  1438. {
  1439. return;
  1440. }
  1441. DerefDdp = TRUE;
  1442. }
  1443. do
  1444. {
  1445. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  1446. sizeof(NBPHDR) + MAX_NBP_TUPLELENGTH,
  1447. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  1448. break;
  1449. Datagram = pBuffDesc->bd_CharBuffer;
  1450. ((PNBPHDR)Datagram)->_NbpId = (BYTE)NbpId;
  1451. ((PNBPHDR)Datagram)->_CmdAndTupleCnt = (NBP_LOOKUP << 4) + 1;
  1452. Len = sizeof(NBPHDR) +
  1453. atalkNbpEncodeTuple(pNbpTuple,
  1454. NULL,
  1455. 0,
  1456. 0,
  1457. Datagram+sizeof(NBPHDR));
  1458. Dst.ata_Node = ATALK_BROADCAST_NODE;
  1459. Dst.ata_Socket = NAMESINFORMATION_SOCKET;
  1460. if (EXT_NET(pPortDesc))
  1461. {
  1462. // Send to "0000FF" at correct zone multicast address
  1463. Dst.ata_Network = CABLEWIDE_BROADCAST_NETWORK;
  1464. AtalkZipMulticastAddrForZone(pPortDesc,
  1465. pNbpTuple->tpl_Zone,
  1466. pNbpTuple->tpl_ZoneLen,
  1467. MulticastAddr);
  1468. }
  1469. else
  1470. {
  1471. // Send to "nnnnFF" as broadcast
  1472. Dst.ata_Network = pPortDesc->pd_NetworkRange.anr_FirstNetwork;
  1473. }
  1474. // Set the length in the buffer descriptor.
  1475. AtalkSetSizeOfBuffDescData(pBuffDesc, (USHORT)Len);
  1476. ASSERT(pBuffDesc->bd_Length > 0);
  1477. SendInfo.sc_TransmitCompletion = atalkNbpSendComplete;
  1478. SendInfo.sc_Ctx1 = pBuffDesc;
  1479. // SendInfo.sc_Ctx2 = NULL;
  1480. // SendInfo.sc_Ctx3 = NULL;
  1481. if (!ATALK_SUCCESS(Status = AtalkDdpSend(pDdpAddr,
  1482. &Dst,
  1483. DDPPROTO_NBP,
  1484. FALSE,
  1485. pBuffDesc,
  1486. NULL,
  1487. 0,
  1488. MulticastAddr,
  1489. &SendInfo)))
  1490. {
  1491. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_ERR,
  1492. ("atalkNbpSendLookupDatagram: DdpSend failed %ld\n", Status));
  1493. break;
  1494. }
  1495. Datagram = NULL;
  1496. pBuffDesc = NULL;
  1497. } while (FALSE);
  1498. if (DerefDdp)
  1499. AtalkDdpDereference(pDdpAddr);
  1500. if (pBuffDesc != NULL)
  1501. AtalkFreeBuffDesc(pBuffDesc);
  1502. }
  1503. /*** atalkNbpSendForwardRequest
  1504. *
  1505. */
  1506. LOCAL VOID
  1507. atalkNbpSendForwardRequest(
  1508. IN PDDP_ADDROBJ pDdpAddr,
  1509. IN PRTE pRte,
  1510. IN SHORT NbpId,
  1511. IN PNBPTUPLE pNbpTuple
  1512. )
  1513. {
  1514. PBYTE Datagram = NULL;
  1515. PBUFFER_DESC pBuffDesc = NULL;
  1516. SEND_COMPL_INFO SendInfo;
  1517. ATALK_ERROR ErrorCode;
  1518. ULONG Len;
  1519. ATALK_ADDR Dst;
  1520. do
  1521. {
  1522. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  1523. sizeof(NBPHDR) + MAX_NBP_TUPLELENGTH,
  1524. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  1525. break;
  1526. Datagram = pBuffDesc->bd_CharBuffer;
  1527. ((PNBPHDR)Datagram)->_NbpId = (BYTE)NbpId;
  1528. ((PNBPHDR)Datagram)->_CmdAndTupleCnt = (NBP_FORWARD_REQUEST << 4) + 1;
  1529. Len = sizeof(NBPHDR) +
  1530. atalkNbpEncodeTuple(pNbpTuple,
  1531. NULL,
  1532. 0,
  1533. 0,
  1534. Datagram+sizeof(NBPHDR));
  1535. Dst.ata_Network = pRte->rte_NwRange.anr_FirstNetwork;
  1536. Dst.ata_Node = ANY_ROUTER_NODE;
  1537. Dst.ata_Socket = NAMESINFORMATION_SOCKET;
  1538. // Set the length in the buffer descriptor.
  1539. AtalkSetSizeOfBuffDescData(pBuffDesc, (USHORT)Len);
  1540. ASSERTMSG("Dest in rte 0\n", Dst.ata_Network != CABLEWIDE_BROADCAST_NETWORK);
  1541. ASSERT(pBuffDesc->bd_Length > 0);
  1542. SendInfo.sc_TransmitCompletion = atalkNbpSendComplete;
  1543. SendInfo.sc_Ctx1 = pBuffDesc;
  1544. // SendInfo.sc_Ctx2 = NULL;
  1545. // SendInfo.sc_Ctx3 = NULL;
  1546. ErrorCode = AtalkDdpSend(pDdpAddr,
  1547. &Dst,
  1548. DDPPROTO_NBP,
  1549. FALSE,
  1550. pBuffDesc,
  1551. NULL,
  1552. 0,
  1553. NULL,
  1554. &SendInfo);
  1555. if (!ATALK_SUCCESS(ErrorCode))
  1556. {
  1557. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_ERR,
  1558. ("atalkNbpSendForwardRequest: DdpSend failed %ld\n", ErrorCode));
  1559. break;
  1560. }
  1561. Datagram = NULL;
  1562. pBuffDesc = NULL;
  1563. } while (FALSE);
  1564. if (pBuffDesc != NULL)
  1565. AtalkFreeBuffDesc(pBuffDesc);
  1566. }
  1567. /*** atalkNbpDerefPendName
  1568. *
  1569. */
  1570. VOID
  1571. atalkNbpDerefPendName(
  1572. IN PPEND_NAME pPendName
  1573. )
  1574. {
  1575. PPEND_NAME * ppPendName;
  1576. PDDP_ADDROBJ pDdpAddr = pPendName->pdn_pDdpAddr;
  1577. BOOLEAN Unlink, Found = FALSE;
  1578. KIRQL OldIrql;
  1579. ACQUIRE_SPIN_LOCK(&pPendName->pdn_Lock, &OldIrql);
  1580. Unlink = (--(pPendName->pdn_RefCount) == 0);
  1581. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  1582. ("atalkNbpDerefPendName: New Count %d\n", pPendName->pdn_RefCount));
  1583. RELEASE_SPIN_LOCK(&pPendName->pdn_Lock, OldIrql);
  1584. if (!Unlink)
  1585. return;
  1586. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_INFO,
  1587. ("atalkNbpDerefPendName: Unlinking pPendName\n"));
  1588. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  1589. for (ppPendName = &pDdpAddr->ddpao_PendNames;
  1590. *ppPendName != NULL;
  1591. ppPendName = &(*ppPendName)->pdn_Next)
  1592. {
  1593. if (*ppPendName == pPendName)
  1594. {
  1595. *ppPendName = pPendName->pdn_Next;
  1596. Found = TRUE;
  1597. break;
  1598. }
  1599. }
  1600. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  1601. if (Found)
  1602. {
  1603. AtalkDdpDereference(pDdpAddr);
  1604. }
  1605. else ASSERTMSG("atalkNbpDerefPendName: Could not find\n", 0);
  1606. AtalkUnlockNbpIfNecessary();
  1607. (*pPendName->pdn_pActReq->ar_Completion)(pPendName->pdn_Status, pPendName->pdn_pActReq);
  1608. if (pPendName->pdn_Flags & PDN_FREE_REGDNAME)
  1609. AtalkFreeMemory(pPendName->pdn_pRegdName);
  1610. AtalkFreeMemory(pPendName);
  1611. }
  1612. /*** atalkNbpSendComplete
  1613. *
  1614. */
  1615. VOID FASTCALL
  1616. atalkNbpSendComplete(
  1617. IN NDIS_STATUS Status,
  1618. IN PSEND_COMPL_INFO pSendInfo
  1619. )
  1620. {
  1621. PBUFFER_DESC pBuffDesc = (PBUFFER_DESC)(pSendInfo->sc_Ctx1);
  1622. if (!ATALK_SUCCESS(Status))
  1623. DBGPRINT(DBG_COMP_NBP, DBG_LEVEL_ERR,
  1624. ("atalkNbpSendComplete: Failed %lx, pBuffDesc %lx\n",
  1625. Status, pBuffDesc));
  1626. AtalkFreeBuffDesc(pBuffDesc);
  1627. }
  1628. 
  1629.