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.

3225 lines
80 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. zip.c
  5. Abstract:
  6. This module contains
  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 ZIP
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, AtalkZipInit)
  19. #pragma alloc_text(PAGEINIT, AtalkInitZipStartProcessingOnPort)
  20. #pragma alloc_text(PAGEINIT, atalkZipGetZoneListForPort)
  21. #pragma alloc_text(PAGE_RTR, AtalkZipPacketInRouter)
  22. #pragma alloc_text(PAGE_RTR, atalkZipHandleNetInfo)
  23. #pragma alloc_text(PAGE_RTR, atalkZipHandleReply)
  24. #pragma alloc_text(PAGE_RTR, atalkZipHandleQuery)
  25. #pragma alloc_text(PAGE_RTR, atalkZipHandleAtpRequest)
  26. #pragma alloc_text(PAGE_RTR, atalkZipQueryTimer)
  27. #pragma alloc_text(PAGE_NZ, AtalkZipGetMyZone)
  28. #pragma alloc_text(PAGE_NZ, atalkZipGetMyZoneReply)
  29. #pragma alloc_text(PAGE_NZ, AtalkZipGetZoneList)
  30. #pragma alloc_text(PAGE_NZ, atalkZipGetZoneListReply)
  31. #pragma alloc_text(PAGE_NZ, atalkZipZoneInfoTimer)
  32. #pragma alloc_text(PAGE_NZ, atalkZipSendPacket)
  33. #endif
  34. /*** AtalkZipInit
  35. *
  36. */
  37. ATALK_ERROR
  38. AtalkZipInit(
  39. IN BOOLEAN Init
  40. )
  41. {
  42. if (Init)
  43. {
  44. // Allocate space for zones
  45. AtalkZonesTable = (PZONE *)AtalkAllocZeroedMemory(sizeof(PZONE) * NUM_ZONES_HASH_BUCKETS);
  46. if (AtalkZonesTable == NULL)
  47. {
  48. return ATALK_RESR_MEM;
  49. }
  50. INITIALIZE_SPIN_LOCK(&AtalkZoneLock);
  51. }
  52. else
  53. {
  54. // At this point, we are unloading and there are no race conditions
  55. // or lock contentions. Do not bother locking down the zones table
  56. if (AtalkDesiredZone != NULL)
  57. AtalkZoneDereference(AtalkDesiredZone);
  58. if (AtalkZonesTable != NULL)
  59. {
  60. AtalkFreeMemory(AtalkZonesTable);
  61. AtalkZonesTable = NULL;
  62. }
  63. }
  64. return ATALK_NO_ERROR;
  65. }
  66. /*** AtalkZipStartProcessingOnPort
  67. *
  68. */
  69. BOOLEAN
  70. AtalkInitZipStartProcessingOnPort(
  71. IN PPORT_DESCRIPTOR pPortDesc,
  72. IN PATALK_NODEADDR pRouterNode
  73. )
  74. {
  75. ATALK_ADDR closeAddr;
  76. ATALK_ERROR Status;
  77. KIRQL OldIrql;
  78. BOOLEAN RetCode = FALSE;
  79. PDDP_ADDROBJ pZpDdpAddr=NULL;
  80. // Switch the incoming zip handler to the router version
  81. closeAddr.ata_Network = pRouterNode->atn_Network;
  82. closeAddr.ata_Node = pRouterNode->atn_Node;
  83. closeAddr.ata_Socket = ZONESINFORMATION_SOCKET;
  84. do
  85. {
  86. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  87. pPortDesc->pd_Flags |= PD_ROUTER_STARTING;
  88. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  89. // Close the non-router version of the handler and start the router version
  90. AtalkDdpInitCloseAddress(pPortDesc, &closeAddr);
  91. if (!ATALK_SUCCESS(Status = AtalkDdpOpenAddress(pPortDesc,
  92. ZONESINFORMATION_SOCKET,
  93. pRouterNode,
  94. AtalkZipPacketInRouter,
  95. NULL,
  96. DDPPROTO_ANY,
  97. NULL,
  98. &pZpDdpAddr)))
  99. {
  100. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  101. ("AtalkZipStartProcessingOnPort: AtalkDdpOpenAddress failed %ld\n",
  102. Status));
  103. break;
  104. }
  105. // mark the fact that this is an "internal" socket
  106. pZpDdpAddr->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  107. // Try to get or set the zone information
  108. if (!atalkZipGetZoneListForPort(pPortDesc))
  109. {
  110. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  111. ("AtalkZipStartProcessingOnPort: Failed to get zone list for port\n"));
  112. break;
  113. }
  114. if (!atalkZipQryTmrRunning)
  115. {
  116. AtalkTimerInitialize(&atalkZipQTimer,
  117. atalkZipQueryTimer,
  118. ZIP_QUERY_TIMER);
  119. AtalkTimerScheduleEvent(&atalkZipQTimer);
  120. atalkZipQryTmrRunning = TRUE;
  121. }
  122. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  123. pPortDesc->pd_Flags &= ~PD_ROUTER_STARTING;
  124. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  125. RetCode = TRUE;
  126. } while (FALSE);
  127. return RetCode;
  128. }
  129. /*** AtalkZipPacketIn
  130. *
  131. */
  132. VOID
  133. AtalkZipPacketIn(
  134. IN PPORT_DESCRIPTOR pPortDesc,
  135. IN PDDP_ADDROBJ pDdpAddr,
  136. IN PBYTE pPkt,
  137. IN USHORT PktLen,
  138. IN PATALK_ADDR pSrcAddr,
  139. IN PATALK_ADDR pDstAddr,
  140. IN ATALK_ERROR Status,
  141. IN BYTE DdpType,
  142. IN PVOID pHandlerCtx,
  143. IN BOOLEAN OptimizedPath,
  144. IN PVOID OptimizeCtx
  145. )
  146. {
  147. BYTE CmdType, Flags;
  148. BYTE ZoneLen, DefZoneLen, MulticastAddrLen;
  149. PBYTE pZone, pDefZone, pMulticastAddr;
  150. TIME TimeS, TimeE, TimeD;
  151. ULONG Index;
  152. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  153. TimeS = KeQueryPerformanceCounter(NULL);
  154. do
  155. {
  156. if ((Status == ATALK_SOCKET_CLOSED) ||
  157. (DdpType != DDPPROTO_ZIP))
  158. break;
  159. else if (Status != ATALK_NO_ERROR)
  160. {
  161. break;
  162. }
  163. if (!EXT_NET(pPortDesc))
  164. {
  165. AtalkLogBadPacket(pPortDesc,
  166. pSrcAddr,
  167. pDstAddr,
  168. pPkt,
  169. PktLen);
  170. break;
  171. }
  172. if (PktLen < ZIP_CMD_OFF+1)
  173. {
  174. break;
  175. }
  176. CmdType = pPkt[ZIP_CMD_OFF];
  177. // We only care about Zip Notifies and NetInfo replies
  178. if (((CmdType != ZIP_NOTIFY) && (CmdType != ZIP_NETINFO_REPLY)) ||
  179. (PktLen < (ZIP_ZONELEN_OFF + 1)))
  180. {
  181. break;
  182. }
  183. // If it is a NetInfoReply, then we should be looking for either the
  184. // default or the desired zone
  185. if ((CmdType != ZIP_NETINFO_REPLY) &&
  186. (pPortDesc->pd_Flags & (PD_FINDING_DEFAULT_ZONE | PD_FINDING_DESIRED_ZONE)))
  187. break;
  188. if ((CmdType == ZIP_NETINFO_REPLY) &&
  189. !(pPortDesc->pd_Flags & (PD_FINDING_DEFAULT_ZONE | PD_FINDING_DESIRED_ZONE)))
  190. break;
  191. // If it is a Notify then the desired zone must be valid
  192. if ((CmdType == ZIP_NOTIFY) &&
  193. !(pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE))
  194. break;
  195. // We have a NetInfoReply or a Notify. Handle it
  196. Flags = pPkt[ZIP_FLAGS_OFF];
  197. Index = ZIP_ZONELEN_OFF;
  198. ZoneLen = pPkt[ZIP_ZONELEN_OFF];
  199. Index ++;
  200. if ((ZoneLen > MAX_ZONE_LENGTH) || (PktLen < (Index + ZoneLen)))
  201. {
  202. AtalkLogBadPacket(pPortDesc,
  203. pSrcAddr,
  204. pDstAddr,
  205. pPkt,
  206. PktLen);
  207. break;
  208. }
  209. pZone = pPkt+Index;
  210. Index += ZoneLen;
  211. // If we are looking for a desired zone and we get a late default zone
  212. // response then toss this packet
  213. if ((CmdType == ZIP_NETINFO_REPLY) && (ZoneLen == 0) &&
  214. (pPortDesc->pd_Flags & (PD_FINDING_DESIRED_ZONE)) &&
  215. (pPortDesc->pd_InitialDesiredZone != NULL))
  216. {
  217. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  218. ("AtalkZipPacketIn: dropping a NetInfoReply packet\n"));
  219. break;
  220. }
  221. // If we're requesting the zone name, make sure the response matches
  222. // our request. ZoneLen will be zero when we're looking for the def
  223. // zone, so we won't do this test
  224. if ((CmdType == ZIP_NETINFO_REPLY) &&
  225. (ZoneLen != 0) &&
  226. (pPortDesc->pd_InitialDesiredZone != NULL))
  227. {
  228. BOOLEAN NoMatch = FALSE;
  229. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  230. ASSERT(!(pPortDesc->pd_Flags & PD_ROUTER_RUNNING) ||
  231. (pPortDesc->pd_Flags & PD_FINDING_DESIRED_ZONE));
  232. if (!AtalkFixedCompareCaseInsensitive(pZone,
  233. ZoneLen,
  234. pPortDesc->pd_InitialDesiredZone->zn_Zone,
  235. pPortDesc->pd_InitialDesiredZone->zn_ZoneLen))
  236. {
  237. NoMatch = TRUE;
  238. }
  239. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  240. if (NoMatch)
  241. break;
  242. }
  243. // If its a Notify, make sure we're in the zone that is being changed
  244. if (CmdType == ZIP_NOTIFY)
  245. {
  246. BOOLEAN NoMatch = FALSE;
  247. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  248. if (!AtalkFixedCompareCaseInsensitive(pZone, ZoneLen,
  249. pPortDesc->pd_DesiredZone->zn_Zone,
  250. pPortDesc->pd_DesiredZone->zn_ZoneLen))
  251. {
  252. NoMatch = TRUE;
  253. }
  254. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  255. if (NoMatch)
  256. break;
  257. }
  258. if (PktLen < (Index + 1))
  259. {
  260. AtalkLogBadPacket(pPortDesc,
  261. pSrcAddr,
  262. pDstAddr,
  263. pPkt,
  264. PktLen);
  265. break;
  266. }
  267. MulticastAddrLen = pPkt[Index++];
  268. if (MulticastAddrLen != pPortDesc->pd_BroadcastAddrLen)
  269. {
  270. AtalkLogBadPacket(pPortDesc,
  271. pSrcAddr,
  272. pDstAddr,
  273. pPkt,
  274. PktLen);
  275. break;
  276. }
  277. if (PktLen < (Index + MulticastAddrLen))
  278. {
  279. AtalkLogBadPacket(pPortDesc,
  280. pSrcAddr,
  281. pDstAddr,
  282. pPkt,
  283. PktLen);
  284. break;
  285. }
  286. pMulticastAddr = pPkt + Index;
  287. Index += MulticastAddrLen;
  288. #if 0
  289. if (Flags & ZIP_USE_BROADCAST_FLAG)
  290. pMulticastAddr = pPortDesc->pd_BroadcastAddr;
  291. #endif
  292. // Grab second name, if needed or present
  293. DefZoneLen = 0;
  294. if ((CmdType == ZIP_NOTIFY) || (PktLen > Index))
  295. {
  296. if (PktLen < (Index+1))
  297. {
  298. AtalkLogBadPacket(pPortDesc,
  299. pSrcAddr,
  300. pDstAddr,
  301. pPkt,
  302. PktLen);
  303. break;
  304. }
  305. DefZoneLen = pPkt[Index++];
  306. if ((DefZoneLen == 0) ||
  307. (DefZoneLen > MAX_ZONE_LENGTH) ||
  308. (PktLen < (Index+DefZoneLen)))
  309. {
  310. AtalkLogBadPacket(pPortDesc,
  311. pSrcAddr,
  312. pDstAddr,
  313. pPkt,
  314. PktLen);
  315. break;
  316. }
  317. pDefZone = pPkt+Index;
  318. Index += DefZoneLen;
  319. }
  320. // Make default zone be the new one. We may not have a default/new
  321. // zone in netinfo reply case and we requested for the correct zone
  322. if (DefZoneLen == 0)
  323. {
  324. pDefZone = pZone;
  325. DefZoneLen = ZoneLen;
  326. }
  327. // Make sure the port lock is released before calling any depend/ddp
  328. // etc. routines.
  329. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  330. // If we're just looking for the default zone, set here and note
  331. // our mission completed
  332. if ((pPortDesc->pd_Flags & PD_FINDING_DEFAULT_ZONE) &&
  333. (ZoneLen == 0))
  334. {
  335. if (pPortDesc->pd_DefaultZone != NULL)
  336. AtalkZoneDereference(pPortDesc->pd_DefaultZone);
  337. pPortDesc->pd_DefaultZone = AtalkZoneReferenceByName(pDefZone, DefZoneLen);
  338. if (pPortDesc->pd_DefaultZone == NULL)
  339. {
  340. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  341. RES_LOG_ERROR();
  342. break;
  343. }
  344. pPortDesc->pd_Flags |= PD_VALID_DEFAULT_ZONE;
  345. pPortDesc->pd_Flags &= ~PD_FINDING_DEFAULT_ZONE;
  346. }
  347. // Now we want to accept all of the information about 'thiszone'
  348. // for the nodes on the current port
  349. // If the new multicast address is different, remove the old and
  350. // set the new. Don't allow changes to the 'broadcast' multicast
  351. // address.
  352. if (pPortDesc->pd_Flags & PD_FINDING_DESIRED_ZONE)
  353. {
  354. if (!AtalkFixedCompareCaseSensitive(pMulticastAddr,
  355. MulticastAddrLen,
  356. pPortDesc->pd_ZoneMulticastAddr,
  357. MulticastAddrLen))
  358. {
  359. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  360. (*pPortDesc->pd_RemoveMulticastAddr)(pPortDesc,
  361. pMulticastAddr,
  362. FALSE,
  363. NULL,
  364. NULL);
  365. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  366. }
  367. if (!AtalkFixedCompareCaseSensitive(pMulticastAddr,
  368. MulticastAddrLen,
  369. pPortDesc->pd_BroadcastAddr,
  370. MulticastAddrLen))
  371. {
  372. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  373. (*pPortDesc->pd_AddMulticastAddr)(pPortDesc,
  374. pMulticastAddr,
  375. FALSE,
  376. NULL,
  377. NULL);
  378. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  379. }
  380. RtlCopyMemory(pPortDesc->pd_ZoneMulticastAddr,
  381. pMulticastAddr,
  382. MulticastAddrLen);
  383. }
  384. // Finally set this cable range if this is a net info reply
  385. if (CmdType == ZIP_NETINFO_REPLY)
  386. {
  387. GETSHORT2SHORT(&pPortDesc->pd_NetworkRange.anr_FirstNetwork,
  388. pPkt+ZIP_CABLE_RANGE_START_OFF);
  389. GETSHORT2SHORT(&pPortDesc->pd_NetworkRange.anr_LastNetwork,
  390. pPkt+ZIP_CABLE_RANGE_END_OFF);
  391. if (!(pPortDesc->pd_Flags & PD_ROUTER_STARTING))
  392. {
  393. pPortDesc->pd_ARouter.atn_Network = pSrcAddr->ata_Network;
  394. pPortDesc->pd_ARouter.atn_Node = pSrcAddr->ata_Node;
  395. }
  396. pPortDesc->pd_Flags |= PD_SEEN_ROUTER_RECENTLY;
  397. KeSetEvent(&pPortDesc->pd_SeenRouterEvent, IO_NETWORK_INCREMENT, FALSE);
  398. }
  399. // Now that we know the zone
  400. if (pPortDesc->pd_Flags & PD_FINDING_DESIRED_ZONE)
  401. {
  402. pPortDesc->pd_Flags &= ~PD_FINDING_DESIRED_ZONE;
  403. pPortDesc->pd_Flags |= PD_VALID_DESIRED_ZONE;
  404. if (pPortDesc->pd_DesiredZone != NULL)
  405. AtalkZoneDereference(pPortDesc->pd_DesiredZone);
  406. pPortDesc->pd_DesiredZone = AtalkZoneReferenceByName(pDefZone, DefZoneLen);
  407. if (pPortDesc->pd_DesiredZone == NULL)
  408. {
  409. pPortDesc->pd_Flags &= ~PD_VALID_DESIRED_ZONE;
  410. RES_LOG_ERROR();
  411. }
  412. }
  413. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  414. TimeE = KeQueryPerformanceCounter(NULL);
  415. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  416. INTERLOCKED_ADD_LARGE_INTGR_DPC(
  417. &pPortDesc->pd_PortStats.prtst_ZipPacketInProcessTime,
  418. TimeD,
  419. &AtalkStatsLock.SpinLock);
  420. INTERLOCKED_INCREMENT_LONG_DPC(
  421. &pPortDesc->pd_PortStats.prtst_NumZipPacketsIn,
  422. &AtalkStatsLock.SpinLock);
  423. } while (FALSE);
  424. }
  425. /*** AtalkZipPacketInRouter
  426. *
  427. */
  428. VOID
  429. AtalkZipPacketInRouter(
  430. IN PPORT_DESCRIPTOR pPortDesc,
  431. IN PDDP_ADDROBJ pDdpAddr,
  432. IN PBYTE pPkt,
  433. IN USHORT PktLen,
  434. IN PATALK_ADDR pSrcAddr,
  435. IN PATALK_ADDR pDstAddr,
  436. IN ATALK_ERROR Status,
  437. IN BYTE DdpType,
  438. IN PVOID pHandlerCtx,
  439. IN BOOLEAN OptimizedPath,
  440. IN PVOID OptimizeCtx
  441. )
  442. {
  443. BYTE CmdType;
  444. TIME TimeS, TimeE, TimeD;
  445. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  446. TimeS = KeQueryPerformanceCounter(NULL);
  447. do
  448. {
  449. if (Status == ATALK_SOCKET_CLOSED)
  450. break;
  451. else if (Status != ATALK_NO_ERROR)
  452. {
  453. break;
  454. }
  455. if (DdpType == DDPPROTO_ZIP)
  456. {
  457. if (PktLen < ZIP_FIRST_NET_OFF)
  458. {
  459. break;
  460. }
  461. CmdType = pPkt[ZIP_CMD_OFF];
  462. switch (CmdType)
  463. {
  464. case ZIP_NETINFO_REPLY:
  465. case ZIP_NOTIFY:
  466. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  467. ("AtalkZipPacketInRouter: Ignoring %s\n",
  468. (CmdType == ZIP_NOTIFY) ? "Notify" : "NetInfoReply"));
  469. break;
  470. case ZIP_GET_NETINFO:
  471. // We do not want to do a thing if we're starting up
  472. if (pPortDesc->pd_Flags & PD_ROUTER_STARTING)
  473. break;
  474. if (!EXT_NET(pPortDesc))
  475. {
  476. AtalkLogBadPacket(pPortDesc,
  477. pSrcAddr,
  478. pDstAddr,
  479. pPkt,
  480. PktLen);
  481. break;
  482. }
  483. if (pPortDesc->pd_ZoneList == NULL)
  484. break; // Not fully up yet !
  485. if (PktLen < ZIP_REQ_ZONENAME_OFF)
  486. {
  487. AtalkLogBadPacket(pPortDesc,
  488. pSrcAddr,
  489. pDstAddr,
  490. pPkt,
  491. PktLen);
  492. break;
  493. }
  494. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  495. ("AtalkZipPacketInRouter: GetNetInfo Port %Z\n",
  496. &pPortDesc->pd_AdapterKey));
  497. atalkZipHandleNetInfo(pPortDesc,
  498. pDdpAddr,
  499. pSrcAddr,
  500. pDstAddr,
  501. pPkt,
  502. PktLen);
  503. break;
  504. case ZIP_EXT_REPLY:
  505. case ZIP_REPLY:
  506. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  507. ("AtalkZipPacketInRouter: %sReply Port %Z\n",
  508. (CmdType == ZIP_REPLY) ? "" : "Extended",
  509. &pPortDesc->pd_AdapterKey));
  510. atalkZipHandleReply(pDdpAddr, pSrcAddr, pPkt, PktLen);
  511. break;
  512. case ZIP_QUERY:
  513. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  514. ("AtalkZipPacketInRouter: Query Port %Z\n",
  515. &pPortDesc->pd_AdapterKey));
  516. // We do not want to do a thing if we're starting up
  517. if (pPortDesc->pd_Flags & PD_ROUTER_STARTING)
  518. break;
  519. atalkZipHandleQuery(pPortDesc, pDdpAddr, pSrcAddr, pPkt, PktLen);
  520. break;
  521. default:
  522. AtalkLogBadPacket(pPortDesc,
  523. pSrcAddr,
  524. pDstAddr,
  525. pPkt,
  526. PktLen);
  527. break;
  528. }
  529. }
  530. else if (DdpType == DDPPROTO_ATP)
  531. {
  532. USHORT TrId, StartIndex;
  533. if (PktLen < ATP_ZIP_START_INDEX_OFF+1)
  534. {
  535. ASSERT(0);
  536. break;
  537. }
  538. // We do not want to do a thing if we're starting up
  539. if (pPortDesc->pd_Flags & PD_ROUTER_STARTING)
  540. break;
  541. // This had better be a GetZoneList, a GetMyZone ATP request
  542. if ((pPkt[ATP_CMD_CONTROL_OFF] & ATP_FUNC_MASK) != ATP_REQUEST)
  543. break;
  544. if (pPkt[ATP_BITMAP_OFF] != 1)
  545. {
  546. AtalkLogBadPacket(pPortDesc,
  547. pSrcAddr,
  548. pDstAddr,
  549. pPkt,
  550. PktLen);
  551. break;
  552. }
  553. GETSHORT2SHORT(&TrId, pPkt + ATP_TRANS_ID_OFF);
  554. CmdType = pPkt[ATP_ZIP_CMD_OFF];
  555. if ((CmdType != ZIP_GET_ZONE_LIST) &&
  556. (CmdType != ZIP_GET_MY_ZONE) &&
  557. (CmdType != ZIP_GET_LOCAL_ZONES))
  558. {
  559. AtalkLogBadPacket(pPortDesc,
  560. pSrcAddr,
  561. pDstAddr,
  562. pPkt,
  563. PktLen);
  564. break;
  565. }
  566. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  567. ("ZIP: Received atp type command %d\n", CmdType));
  568. // Get start index. Not meaningful for GetMyZone
  569. GETSHORT2SHORT(&StartIndex, pPkt+ATP_ZIP_START_INDEX_OFF);
  570. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  571. ("AtalkZipPacketInRouter: AtpRequest %d, Port %Z\n",
  572. CmdType, &pPortDesc->pd_AdapterKey));
  573. atalkZipHandleAtpRequest(pPortDesc, pDdpAddr, pSrcAddr,
  574. CmdType, TrId, StartIndex);
  575. }
  576. } while (FALSE);
  577. TimeE = KeQueryPerformanceCounter(NULL);
  578. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  579. INTERLOCKED_ADD_LARGE_INTGR_DPC(
  580. &pPortDesc->pd_PortStats.prtst_ZipPacketInProcessTime,
  581. TimeD,
  582. &AtalkStatsLock.SpinLock);
  583. INTERLOCKED_INCREMENT_LONG_DPC(
  584. &pPortDesc->pd_PortStats.prtst_NumZipPacketsIn,
  585. &AtalkStatsLock.SpinLock);
  586. }
  587. /*** atalkZipHandleNetInfo
  588. *
  589. */
  590. VOID
  591. atalkZipHandleNetInfo(
  592. IN PPORT_DESCRIPTOR pPortDesc,
  593. IN PDDP_ADDROBJ pDdpAddr,
  594. IN PATALK_ADDR pSrcAddr,
  595. IN PATALK_ADDR pDstAddr,
  596. IN PBYTE pPkt,
  597. IN USHORT PktLen
  598. )
  599. {
  600. PBUFFER_DESC pBuffDesc;
  601. BYTE ZoneLen;
  602. PBYTE Datagram, pZoneName;
  603. ATALK_ADDR SrcAddr = *pSrcAddr;
  604. ATALK_ERROR error;
  605. BOOLEAN UseDefZone = FALSE;
  606. USHORT index;
  607. SEND_COMPL_INFO SendInfo;
  608. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  609. do
  610. {
  611. // Get the zone name out of the request
  612. ZoneLen = pPkt[ZIP_REQ_ZONELEN_OFF];
  613. if ((ZoneLen > MAX_ZONE_LENGTH) ||
  614. (PktLen < (USHORT)(ZoneLen + ZIP_REQ_ZONENAME_OFF)))
  615. {
  616. AtalkLogBadPacket(pPortDesc,
  617. pSrcAddr,
  618. pDstAddr,
  619. pPkt,
  620. PktLen);
  621. break;
  622. }
  623. pZoneName = pPkt+ZIP_REQ_ZONENAME_OFF;
  624. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  625. MAX_DGRAM_SIZE,
  626. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  627. {
  628. break;
  629. }
  630. Datagram = pBuffDesc->bd_CharBuffer;
  631. // Format a GetNetInfo reply command
  632. Datagram[ZIP_CMD_OFF] = ZIP_NETINFO_REPLY;
  633. Datagram[ZIP_FLAGS_OFF] = 0;
  634. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  635. if ((ZoneLen == 0) ||
  636. !AtalkZoneNameOnList(pZoneName, ZoneLen, pPortDesc->pd_ZoneList))
  637. {
  638. Datagram[ZIP_FLAGS_OFF] |= ZIP_ZONE_INVALID_FLAG;
  639. UseDefZone = TRUE;
  640. }
  641. if (AtalkZoneNumOnList(pPortDesc->pd_ZoneList) == 1)
  642. Datagram[ZIP_FLAGS_OFF] |= ZIP_ONLYONE_ZONE_FLAG;
  643. // Add our cable range
  644. PUTSHORT2SHORT(&Datagram[ZIP_FIRST_NET_OFF],
  645. pPortDesc->pd_NetworkRange.anr_FirstNetwork);
  646. PUTSHORT2SHORT(Datagram +ZIP_LAST_NET_OFF,
  647. pPortDesc->pd_NetworkRange.anr_LastNetwork);
  648. // Echo back the requested zone name
  649. Datagram[ZIP_REQ_ZONELEN_OFF] = ZoneLen;
  650. RtlCopyMemory(Datagram+ZIP_REQ_ZONENAME_OFF, pZoneName, ZoneLen);
  651. index = ZIP_REQ_ZONENAME_OFF + ZoneLen;
  652. // Place in the correct zone multicast address
  653. Datagram[index++] = (BYTE)(pPortDesc->pd_BroadcastAddrLen);
  654. if (UseDefZone)
  655. {
  656. pZoneName = pPortDesc->pd_DefaultZone->zn_Zone;
  657. ZoneLen = pPortDesc->pd_DefaultZone->zn_ZoneLen;
  658. }
  659. AtalkZipMulticastAddrForZone(pPortDesc, pZoneName, ZoneLen, Datagram + index);
  660. index += pPortDesc->pd_BroadcastAddrLen;
  661. // If we need it, add in the default zone
  662. if (UseDefZone)
  663. {
  664. Datagram[index++] = ZoneLen = pPortDesc->pd_DefaultZone->zn_ZoneLen;
  665. RtlCopyMemory(Datagram + index, pPortDesc->pd_DefaultZone->zn_Zone, ZoneLen);
  666. index += ZoneLen;
  667. }
  668. // If the request came as a cable-wide broadcast and its
  669. // source network is not valid for this port, then we want
  670. // to respond to cable-wide broadcast rather than the source
  671. if ((pDstAddr->ata_Network == CABLEWIDE_BROADCAST_NETWORK) &&
  672. (pDstAddr->ata_Node == ATALK_BROADCAST_NODE) &&
  673. !WITHIN_NETWORK_RANGE(pSrcAddr->ata_Network,
  674. &pPortDesc->pd_NetworkRange) &&
  675. !WITHIN_NETWORK_RANGE(pSrcAddr->ata_Network,
  676. &AtalkStartupNetworkRange))
  677. {
  678. SrcAddr.ata_Network = CABLEWIDE_BROADCAST_NETWORK;
  679. SrcAddr.ata_Node = ATALK_BROADCAST_NODE;
  680. }
  681. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  682. // Set the length in the buffer descriptor.
  683. AtalkSetSizeOfBuffDescData(pBuffDesc, index);
  684. // Finally, send this out
  685. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  686. ("atalkZipHandleNetInfo: Sending Reply to %d.%d.%d\n",
  687. SrcAddr.ata_Network, SrcAddr.ata_Node, SrcAddr.ata_Socket));
  688. SendInfo.sc_TransmitCompletion = atalkZipSendComplete;
  689. SendInfo.sc_Ctx1 = pBuffDesc;
  690. // SendInfo.sc_Ctx2 = NULL;
  691. // SendInfo.sc_Ctx3 = NULL;
  692. error = AtalkDdpSend(pDdpAddr,
  693. &SrcAddr,
  694. DDPPROTO_ZIP,
  695. FALSE,
  696. pBuffDesc,
  697. NULL,
  698. 0,
  699. NULL,
  700. &SendInfo);
  701. if (!ATALK_SUCCESS(error))
  702. {
  703. AtalkFreeBuffDesc(pBuffDesc);
  704. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  705. ("atalkZipHandleNetInfo: AtalkDdpSend %ld\n", error));
  706. }
  707. } while (FALSE);
  708. }
  709. /*** atalkZipHandleReply
  710. *
  711. */
  712. VOID
  713. atalkZipHandleReply(
  714. IN PDDP_ADDROBJ pDdpAddr,
  715. IN PATALK_ADDR pSrcAddr,
  716. IN PBYTE pPkt,
  717. IN USHORT PktLen
  718. )
  719. {
  720. ULONG index, TotalNetCnt;
  721. PRTE pRte = NULL;
  722. PBYTE ZoneName;
  723. USHORT NetNum;
  724. BYTE CmdType, NwCnt, NumZonesOnNet, ZoneLen;
  725. BOOLEAN RteLocked = FALSE;
  726. BOOLEAN ExtReply = FALSE;
  727. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  728. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  729. ("atalkZipHandleReply: Enetered\n"));
  730. // For a zip extended reply, the network count is really not
  731. // the # of networks contained in the packet. It is the total #
  732. // of zones on the single network that is described by the reply
  733. NwCnt = NumZonesOnNet = pPkt[ZIP_NW_CNT_OFF];
  734. CmdType = pPkt[ZIP_CMD_OFF];
  735. do
  736. {
  737. // Walk through the reply packet (assuming we asked for the
  738. // contained information). We're still using NwCnt when
  739. // processing an extended reply, but that's okay 'cause it
  740. // will certainly be at least the # of zones contained in
  741. // this packet. The '+3' guarantees that we really have
  742. // network # and node
  743. for (index = ZIP_FIRST_NET_OFF, TotalNetCnt = 0;
  744. (TotalNetCnt < NwCnt) && ((index + 3 ) <= PktLen);
  745. TotalNetCnt ++)
  746. {
  747. if (pRte != NULL)
  748. {
  749. if (RteLocked)
  750. {
  751. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  752. RteLocked = FALSE;
  753. }
  754. AtalkRtmpDereferenceRte(pRte, FALSE);
  755. pRte = NULL;
  756. }
  757. // Get the next netwotk #, if it's not in our routing
  758. // table (or not the start of a range), then we certainly
  759. // don't care about its zone name
  760. GETSHORT2SHORT(&NetNum, pPkt+index);
  761. index += sizeof(USHORT);
  762. ZoneLen = pPkt[index++];
  763. if (((pRte = AtalkRtmpReferenceRte(NetNum)) == NULL) ||
  764. (pRte->rte_NwRange.anr_FirstNetwork != NetNum))
  765. {
  766. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  767. ("atalkZipHandleReply: Don't know about this range %d\n",
  768. NetNum));
  769. index += ZoneLen;
  770. continue;
  771. }
  772. // Validate the zone name
  773. if ((ZoneLen == 0) || (ZoneLen > MAX_ZONE_LENGTH) ||
  774. ((index + ZoneLen) > PktLen))
  775. {
  776. AtalkLogBadPacket(pDdpAddr->ddpao_Node->an_Port,
  777. pSrcAddr,
  778. NULL,
  779. pPkt,
  780. PktLen);
  781. break;
  782. }
  783. // Conditionally move the zone name into the routing table
  784. ZoneName = pPkt+index;
  785. index += ZoneLen;
  786. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  787. RteLocked = TRUE;
  788. if (AtalkZoneNameOnList(ZoneName, ZoneLen, pRte->rte_ZoneList))
  789. {
  790. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  791. ("atalkZipHandleReply: Already have this zone\n"));
  792. continue;
  793. }
  794. // Check for somebody out there trying to add another zone to
  795. // our directly connected non-extended network and we already
  796. // know its zone.
  797. if ((pRte->rte_NumHops == 0) &&
  798. !EXT_NET(pRte->rte_PortDesc) &&
  799. (AtalkZoneNumOnList(pRte->rte_ZoneList) == 1))
  800. {
  801. AtalkLogBadPacket(pDdpAddr->ddpao_Node->an_Port,
  802. pSrcAddr,
  803. NULL,
  804. pPkt,
  805. PktLen);
  806. continue;
  807. }
  808. // Add to the list now
  809. pRte->rte_ZoneList = AtalkZoneAddToList(pRte->rte_ZoneList,
  810. ZoneName,
  811. ZoneLen);
  812. if (pRte->rte_ZoneList == NULL)
  813. {
  814. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  815. ("atalkZipHandleReply: Failed to add zone to list\n"));
  816. pRte->rte_Flags &= ~RTE_ZONELIST_VALID;
  817. continue;
  818. }
  819. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  820. ("atalkZipHandleReply: # of zones known so far %d\n",
  821. AtalkZoneNumOnList(pRte->rte_ZoneList)));
  822. // If not an extended reply, we know that we have all
  823. // of the information about a given network contained
  824. // in this packet, so we can go ahead and mark the zone
  825. // list valid now
  826. if (!ExtReply)
  827. pRte->rte_Flags |= RTE_ZONELIST_VALID;
  828. }
  829. // If we just handled an extended reply, do we now know all
  830. // that we should know about the specified network ?
  831. if (pRte != NULL)
  832. {
  833. if (ExtReply)
  834. {
  835. if (!RteLocked)
  836. {
  837. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  838. RteLocked = TRUE;
  839. }
  840. if (AtalkZoneNumOnList(pRte->rte_ZoneList) >= NumZonesOnNet)
  841. pRte->rte_Flags |= RTE_ZONELIST_VALID;
  842. }
  843. if (RteLocked)
  844. {
  845. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  846. // RteLocked = FALSE;
  847. }
  848. AtalkRtmpDereferenceRte(pRte, FALSE);
  849. // pRte = NULL;
  850. }
  851. } while (FALSE);
  852. }
  853. /*** atalkZipHandleQuery
  854. *
  855. */
  856. VOID
  857. atalkZipHandleQuery(
  858. IN PPORT_DESCRIPTOR pPortDesc,
  859. IN PDDP_ADDROBJ pDdpAddr,
  860. IN PATALK_ADDR pSrcAddr,
  861. IN PBYTE pPkt,
  862. IN USHORT PktLen
  863. )
  864. {
  865. PRTE pRte = NULL;
  866. PBUFFER_DESC pBuffDesc,
  867. pBuffDescStart = NULL,
  868. *ppBuffDesc = &pBuffDescStart;
  869. PZONE_LIST pZoneList;
  870. PBYTE Datagram;
  871. ATALK_ERROR error;
  872. ULONG i, CurrNumZones, PrevNumZones, TotalNetCnt;
  873. ULONG NwCnt, NetCntInPkt;
  874. USHORT NetNum, Size;
  875. BOOLEAN AllocNewBuffDesc = TRUE, NewPkt = TRUE;
  876. BOOLEAN PortLocked = FALSE, RteLocked = FALSE;
  877. BYTE CurrReply, NextReply;
  878. SEND_COMPL_INFO SendInfo;
  879. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  880. CurrNumZones = 0;
  881. do
  882. {
  883. // Walk through the query packet building reply packets that
  884. // have as much information as we know.
  885. // When sending replies, we will always send a reply about a
  886. // network that has more than one zone as an extended reply.
  887. // As were walking the query list, and we encounter a couple of
  888. // networks that have only one zone, we'll pack as many of
  889. // these as we can into a non-extended reply
  890. NwCnt = pPkt[ZIP_NW_CNT_OFF];
  891. for (NetCntInPkt = 0, TotalNetCnt = 0, i = ZIP_FIRST_NET_OFF;
  892. (TotalNetCnt < NwCnt) && ((i + sizeof(SHORT)) <= PktLen);
  893. i += sizeof(USHORT), TotalNetCnt++)
  894. {
  895. // Dereference any previous Rtes
  896. if (pRte != NULL)
  897. {
  898. if (RteLocked)
  899. {
  900. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  901. RteLocked = FALSE;
  902. }
  903. AtalkRtmpDereferenceRte(pRte, FALSE);
  904. pRte = NULL;
  905. }
  906. if (PortLocked)
  907. {
  908. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  909. PortLocked = FALSE;
  910. }
  911. // Grab the next network number from the query packet,
  912. // if we don't know about the network, or we don't know
  913. // the zone name, continue with the next network number
  914. GETSHORT2SHORT(&NetNum, pPkt+i);
  915. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  916. if ((WITHIN_NETWORK_RANGE(NetNum,&pPortDesc->pd_NetworkRange)) &&
  917. (pPortDesc->pd_ZoneList != NULL))
  918. {
  919. pZoneList = pPortDesc->pd_ZoneList;
  920. PortLocked = TRUE;
  921. }
  922. else
  923. {
  924. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  925. if (((pRte = AtalkRtmpReferenceRte(NetNum)) == NULL) ||
  926. (!WITHIN_NETWORK_RANGE(NetNum, &pRte->rte_NwRange)) ||
  927. !(pRte->rte_Flags & RTE_ZONELIST_VALID))
  928. {
  929. continue;
  930. }
  931. else
  932. {
  933. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  934. pZoneList = pRte->rte_ZoneList;
  935. RteLocked = TRUE;
  936. }
  937. }
  938. next_reply:
  939. if (AllocNewBuffDesc)
  940. {
  941. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  942. MAX_DGRAM_SIZE,
  943. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  944. {
  945. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  946. ("\natalkZipHandleQuery: AtalkAllocBuffDesc @1 failed\n"));
  947. break;
  948. }
  949. Size = 0;
  950. Datagram = pBuffDesc->bd_CharBuffer;
  951. *ppBuffDesc = pBuffDesc;
  952. pBuffDesc->bd_Next = NULL;
  953. ppBuffDesc = &pBuffDesc->bd_Next;
  954. AllocNewBuffDesc = FALSE;
  955. }
  956. // What type of response does this network want ?
  957. // Copy the previous network's zone count. In case of the first
  958. // pass, make it same.
  959. PrevNumZones = CurrNumZones;
  960. CurrNumZones = AtalkZoneNumOnList(pZoneList);
  961. if (i == ZIP_FIRST_NET_OFF)
  962. PrevNumZones = CurrNumZones;
  963. ASSERT (CurrNumZones != 0);
  964. NextReply = ZIP_REPLY;
  965. if (CurrNumZones > 1)
  966. {
  967. // We start a new packet for each extended network
  968. NewPkt = TRUE;
  969. NextReply = ZIP_EXT_REPLY;
  970. if (NetCntInPkt > 0)
  971. {
  972. Datagram[ZIP_CMD_OFF] = CurrReply;
  973. if (CurrReply == ZIP_REPLY)
  974. Datagram[ZIP_NW_CNT_OFF] = (BYTE)NetCntInPkt;
  975. else Datagram[ZIP_NW_CNT_OFF] = (BYTE)PrevNumZones;
  976. AllocNewBuffDesc = TRUE;
  977. pBuffDesc->bd_Length = Size;
  978. NetCntInPkt = 0;
  979. goto next_reply;
  980. }
  981. }
  982. // Walk the zone list
  983. for (; pZoneList != NULL; pZoneList = pZoneList->zl_Next)
  984. {
  985. PZONE pZone = pZoneList->zl_pZone;
  986. // If we're starting to build a new reply packet due to
  987. // either:
  988. //
  989. // 1. first time through
  990. // 2. packet full
  991. // 3. switching reply types
  992. //
  993. // set the index to the first tuple position.
  994. if (NewPkt || (CurrReply != NextReply))
  995. {
  996. if (NetCntInPkt > 0)
  997. {
  998. // Close the current buffdesc and open a new one
  999. // Careful here with the CurrNumZones vs. PrevNumZones
  1000. // If we are going from ExtReply to a Reply, we need
  1001. // to get PrevNumZones. If we are continuing the
  1002. // same ExtReply then we need CurrNumZones.
  1003. Datagram[ZIP_CMD_OFF] = CurrReply;
  1004. if (CurrReply == ZIP_REPLY)
  1005. Datagram[ZIP_NW_CNT_OFF] = (BYTE)NetCntInPkt;
  1006. else
  1007. {
  1008. Datagram[ZIP_NW_CNT_OFF] = (BYTE)CurrNumZones;
  1009. if (CurrReply != NextReply)
  1010. Datagram[ZIP_NW_CNT_OFF] = (BYTE)PrevNumZones;
  1011. }
  1012. pBuffDesc->bd_Length = Size;
  1013. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,MAX_DGRAM_SIZE,
  1014. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  1015. {
  1016. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  1017. ("\natalkZipHandleQuery: AtalkAllocBuffDesc @2 failed\n"));
  1018. break;
  1019. }
  1020. Size = 0;
  1021. Datagram = pBuffDesc->bd_CharBuffer;
  1022. *ppBuffDesc = pBuffDesc;
  1023. pBuffDesc->bd_Next = NULL;
  1024. ppBuffDesc = &pBuffDesc->bd_Next;
  1025. NetCntInPkt = 0;
  1026. }
  1027. Size = ZIP_FIRST_NET_OFF;
  1028. CurrReply = NextReply;
  1029. NewPkt = FALSE;
  1030. }
  1031. // We know the answer to the question. Pack a new
  1032. // network/zone tuple into the reply packet.
  1033. PUTSHORT2SHORT(Datagram+Size, NetNum);
  1034. Size += sizeof(USHORT);
  1035. Datagram[Size++] = pZone->zn_ZoneLen;
  1036. RtlCopyMemory(Datagram + Size,
  1037. pZone->zn_Zone,
  1038. pZone->zn_ZoneLen);
  1039. Size += pZone->zn_ZoneLen;
  1040. NetCntInPkt ++;
  1041. // If we can't hold another big tuple, signal that we
  1042. // should send on the next pass.
  1043. if ((Size + sizeof(USHORT) + sizeof(char) + MAX_ZONE_LENGTH)
  1044. >= MAX_DGRAM_SIZE)
  1045. {
  1046. NewPkt = TRUE;
  1047. }
  1048. }
  1049. if (pBuffDesc == NULL)
  1050. {
  1051. break;
  1052. }
  1053. }
  1054. // Dereference an rte if we broke out the loop above
  1055. if (pRte != NULL)
  1056. {
  1057. ASSERT(!PortLocked);
  1058. if (RteLocked)
  1059. {
  1060. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1061. // RteLocked = FALSE;
  1062. }
  1063. AtalkRtmpDereferenceRte(pRte, FALSE);
  1064. // pRte = NULL;
  1065. }
  1066. if (PortLocked)
  1067. {
  1068. ASSERT(!RteLocked);
  1069. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1070. PortLocked = FALSE;
  1071. }
  1072. // Close the current buffdesc
  1073. if ((!AllocNewBuffDesc) && (pBuffDesc != NULL))
  1074. {
  1075. pBuffDesc->bd_Length = Size;
  1076. if (NetCntInPkt > 0)
  1077. {
  1078. Datagram[ZIP_CMD_OFF] = CurrReply;
  1079. if (CurrReply == ZIP_REPLY)
  1080. Datagram[ZIP_NW_CNT_OFF] = (BYTE)NetCntInPkt;
  1081. else Datagram[ZIP_NW_CNT_OFF] = (BYTE)CurrNumZones;
  1082. }
  1083. }
  1084. // We have a bunch of datagrams ready to be fired off.
  1085. // Make it so. Do not send any with zero lengths, however.
  1086. SendInfo.sc_TransmitCompletion = atalkZipSendComplete;
  1087. // SendInfo.sc_Ctx2 = NULL;
  1088. // SendInfo.sc_Ctx3 = NULL;
  1089. for (pBuffDesc = pBuffDescStart;
  1090. pBuffDesc != NULL;
  1091. pBuffDesc = pBuffDescStart)
  1092. {
  1093. pBuffDescStart = pBuffDesc->bd_Next;
  1094. if (pBuffDesc->bd_Length == 0)
  1095. {
  1096. ASSERT(pBuffDescStart == NULL);
  1097. AtalkFreeBuffDesc(pBuffDesc);
  1098. break;
  1099. }
  1100. // Set the next ptr to be null. Length already set correctly.
  1101. pBuffDesc->bd_Next = NULL;
  1102. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1103. ("atalkZipHandleQuery: Sending Reply to %d.%d.%d\n",
  1104. pSrcAddr->ata_Network, pSrcAddr->ata_Node, pSrcAddr->ata_Socket));
  1105. SendInfo.sc_Ctx1 = pBuffDesc;
  1106. error = AtalkDdpSend(pDdpAddr,
  1107. pSrcAddr,
  1108. DDPPROTO_ZIP,
  1109. FALSE,
  1110. pBuffDesc,
  1111. NULL,
  1112. 0,
  1113. NULL,
  1114. &SendInfo);
  1115. if (!ATALK_SUCCESS(error))
  1116. {
  1117. AtalkFreeBuffDesc(pBuffDesc);
  1118. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1119. ("atalkZipHandleQuery: AtalkDdpSend %ld\n", error));
  1120. }
  1121. }
  1122. } while (FALSE);
  1123. if (PortLocked)
  1124. {
  1125. ASSERT(!RteLocked);
  1126. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1127. }
  1128. }
  1129. /*** atalkZipHandleAtpRequest
  1130. *
  1131. */
  1132. VOID
  1133. atalkZipHandleAtpRequest(
  1134. IN PPORT_DESCRIPTOR pPortDesc,
  1135. IN PDDP_ADDROBJ pDdpAddr,
  1136. IN PATALK_ADDR pSrcAddr,
  1137. IN BYTE CmdType,
  1138. IN USHORT TrId,
  1139. IN USHORT StartIndex
  1140. )
  1141. {
  1142. PBUFFER_DESC pBuffDesc;
  1143. PBYTE Datagram, ZoneName;
  1144. PZONE pZone;
  1145. ATALK_ERROR error;
  1146. int i, ZoneLen, ZoneCnt, CurrZoneIndex, index;
  1147. BYTE LastFlag = 0;
  1148. SEND_COMPL_INFO SendInfo;
  1149. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  1150. do
  1151. {
  1152. // Allocate a buffer descriptor and initialize the header
  1153. if ((pBuffDesc = AtalkAllocBuffDesc(NULL, MAX_DGRAM_SIZE,
  1154. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  1155. {
  1156. break;
  1157. }
  1158. Datagram = pBuffDesc->bd_CharBuffer;
  1159. Datagram[ATP_CMD_CONTROL_OFF] = ATP_RESPONSE + ATP_EOM_MASK;
  1160. Datagram[ATP_SEQ_NUM_OFF] = 0;
  1161. PUTSHORT2SHORT(Datagram + ATP_TRANS_ID_OFF, TrId);
  1162. SendInfo.sc_TransmitCompletion = atalkZipSendComplete;
  1163. SendInfo.sc_Ctx1 = pBuffDesc;
  1164. // SendInfo.sc_Ctx2 = NULL;
  1165. // SendInfo.sc_Ctx3 = NULL;
  1166. if (CmdType == ZIP_GET_MY_ZONE)
  1167. {
  1168. // We really shouldn't be getting this request on an
  1169. // extended network, but go ahead and reply with the
  1170. // "default zone" in this case, of course, reply with
  1171. // "desired zone" for non-extended nets. We are a router,
  1172. // so "desired zone" will always be valid -- as will the
  1173. // default zone for extended net.
  1174. PUTSHORT2SHORT(Datagram+ATP_ZIP_LAST_FLAG_OFF, 0);
  1175. PUTSHORT2SHORT(Datagram+ATP_ZIP_START_INDEX_OFF, 1);
  1176. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1177. if (EXT_NET(pPortDesc))
  1178. {
  1179. ZoneName = pPortDesc->pd_DefaultZone->zn_Zone;
  1180. ZoneLen = pPortDesc->pd_DefaultZone->zn_ZoneLen;
  1181. }
  1182. else
  1183. {
  1184. ZoneName = pPortDesc->pd_DesiredZone->zn_Zone;
  1185. ZoneLen = pPortDesc->pd_DesiredZone->zn_ZoneLen;
  1186. }
  1187. RtlCopyMemory(Datagram+ATP_DATA_OFF+1, ZoneName, ZoneLen);
  1188. Datagram[ATP_DATA_OFF] = (BYTE)ZoneLen;
  1189. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1190. // Set the length in the buffer descriptor.
  1191. AtalkSetSizeOfBuffDescData(pBuffDesc, (USHORT)(ATP_DATA_OFF + 1 + ZoneLen));
  1192. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1193. ("atalkZipHandleAtpReq: Sending GetMyZone Reply to %d.%d.%d\n",
  1194. pSrcAddr->ata_Network, pSrcAddr->ata_Node, pSrcAddr->ata_Socket));
  1195. error = AtalkDdpSend(pDdpAddr,
  1196. pSrcAddr,
  1197. DDPPROTO_ATP,
  1198. FALSE,
  1199. pBuffDesc,
  1200. NULL,
  1201. 0,
  1202. NULL,
  1203. &SendInfo);
  1204. if (!ATALK_SUCCESS(error))
  1205. {
  1206. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1207. ("atalkZipHandleAtpRequest: AtalkDdpSend %ld\n", error));
  1208. }
  1209. break;
  1210. }
  1211. // Either a GetLocalZones or a GetZoneList. Fill the reply packet
  1212. // with as many zones as it'll hold starting at the requested
  1213. // start index
  1214. index = ATP_DATA_OFF;
  1215. if (CmdType == ZIP_GET_LOCAL_ZONES)
  1216. {
  1217. PZONE_LIST pZoneList;
  1218. // For GetLocalZones, we only want to count zones
  1219. // that are on the network that is directly connected
  1220. // to the port on which the request originated. Use the
  1221. // zone list on the port.
  1222. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1223. for (pZoneList = pPortDesc->pd_ZoneList, ZoneCnt = 0, CurrZoneIndex = 0;
  1224. pZoneList != NULL;
  1225. pZoneList = pZoneList->zl_Next)
  1226. {
  1227. // If we have not seen StartIndex zones yet, keep going
  1228. if (++CurrZoneIndex < StartIndex)
  1229. continue;
  1230. pZone = pZoneList->zl_pZone;
  1231. // If this packet cannot hold more, we're done (for now)
  1232. // Fill in the zone count and the last flag
  1233. if ((index + pZone->zn_ZoneLen + 1) >= MAX_DGRAM_SIZE)
  1234. {
  1235. break;
  1236. }
  1237. // Place zone name in the packet
  1238. ASSERT(pZone != NULL);
  1239. Datagram[index] = pZone->zn_ZoneLen;
  1240. RtlCopyMemory(Datagram+index+1,
  1241. pZone->zn_Zone,
  1242. pZone->zn_ZoneLen);
  1243. index += (pZone->zn_ZoneLen + 1);
  1244. ZoneCnt ++;
  1245. }
  1246. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1247. // We've build a packet, set the last flag, if applicable
  1248. LastFlag = (pZoneList == NULL) ? 1 : 0;
  1249. }
  1250. else // This is a ZIP_GET_ZONE_LIST
  1251. {
  1252. BOOLEAN PktFull = FALSE;
  1253. ASSERT (CmdType == ZIP_GET_ZONE_LIST);
  1254. // For GetZoneList, we want all the zones that we know
  1255. // of, so use the AtalkZoneTable.
  1256. ACQUIRE_SPIN_LOCK_DPC(&AtalkZoneLock);
  1257. for (i = 0, ZoneCnt = 0, CurrZoneIndex = 0;
  1258. (i < NUM_ZONES_HASH_BUCKETS) && !PktFull; i++)
  1259. {
  1260. for (pZone = AtalkZonesTable[i];
  1261. pZone != NULL;
  1262. pZone = pZone->zn_Next)
  1263. {
  1264. // If we have not seen StartIndex zones yet, keep going
  1265. if (++CurrZoneIndex < StartIndex)
  1266. continue;
  1267. // If this packet cannot hold more, we're done (for now)
  1268. // Fill in the zone count and the last flag
  1269. if ((index + pZone->zn_ZoneLen + 1) >= MAX_DGRAM_SIZE)
  1270. {
  1271. PktFull = TRUE;
  1272. break;
  1273. }
  1274. // Place zone name in the packet
  1275. Datagram[index] = pZone->zn_ZoneLen;
  1276. RtlCopyMemory(Datagram+index+1,
  1277. pZone->zn_Zone,
  1278. pZone->zn_ZoneLen);
  1279. index += (pZone->zn_ZoneLen + 1);
  1280. ZoneCnt ++;
  1281. }
  1282. }
  1283. RELEASE_SPIN_LOCK_DPC(&AtalkZoneLock);
  1284. // We've build a packet, set the last flag, if applicable
  1285. LastFlag = ((i == NUM_ZONES_HASH_BUCKETS) && (pZone == NULL)) ? 1 : 0;
  1286. }
  1287. // We've build a packet, set the last flag and # of zones in packet
  1288. Datagram[ATP_ZIP_LAST_FLAG_OFF] = LastFlag;
  1289. Datagram[ATP_ZIP_LAST_FLAG_OFF + 1] = 0;
  1290. PUTSHORT2SHORT(Datagram + ATP_ZIP_ZONE_CNT_OFF, ZoneCnt);
  1291. // Set the length in the buffer descriptor.
  1292. AtalkSetSizeOfBuffDescData(pBuffDesc, (USHORT)index);
  1293. // Finally, send this out
  1294. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1295. ("atalkZipHandleAtpReq: Sending LocalZones Reply to %d.%d.%d\n",
  1296. pSrcAddr->ata_Network, pSrcAddr->ata_Node, pSrcAddr->ata_Socket));
  1297. error = AtalkDdpSend(pDdpAddr,
  1298. pSrcAddr,
  1299. DDPPROTO_ATP,
  1300. FALSE,
  1301. pBuffDesc,
  1302. NULL,
  1303. 0,
  1304. NULL,
  1305. &SendInfo);
  1306. if (!ATALK_SUCCESS(error))
  1307. {
  1308. AtalkFreeBuffDesc(pBuffDesc);
  1309. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1310. ("atalkZipHandleAtpRequest: AtalkDdpSend %ld\n", error));
  1311. }
  1312. } while (FALSE);
  1313. }
  1314. /*** AtalkZipMulticastAddrForZone
  1315. *
  1316. */
  1317. VOID
  1318. AtalkZipMulticastAddrForZone(
  1319. IN PPORT_DESCRIPTOR pPortDesc,
  1320. IN PBYTE pZone,
  1321. IN BYTE ZoneLen,
  1322. IN PBYTE MulticastAddr
  1323. )
  1324. {
  1325. USHORT CheckSum;
  1326. BYTE UpCasedZone[MAX_ZONE_LENGTH];
  1327. AtalkUpCase(pZone, ZoneLen, UpCasedZone);
  1328. // Caculate the checksum for the zone
  1329. CheckSum = AtalkDdpCheckSumBuffer(UpCasedZone, ZoneLen, 0);
  1330. switch (pPortDesc->pd_PortType)
  1331. {
  1332. case ELAP_PORT:
  1333. case FDDI_PORT:
  1334. RtlCopyMemory(MulticastAddr,
  1335. AtalkEthernetZoneMulticastAddrsHdr,
  1336. ELAP_MCAST_HDR_LEN);
  1337. MulticastAddr[ELAP_MCAST_HDR_LEN] =
  1338. AtalkEthernetZoneMulticastAddrs[CheckSum % ELAP_ZONE_MULTICAST_ADDRS];
  1339. break;
  1340. case TLAP_PORT:
  1341. RtlCopyMemory(MulticastAddr,
  1342. AtalkTokenRingZoneMulticastAddrsHdr,
  1343. TLAP_MCAST_HDR_LEN);
  1344. RtlCopyMemory(&MulticastAddr[TLAP_MCAST_HDR_LEN],
  1345. AtalkTokenRingZoneMulticastAddrs[CheckSum % TLAP_ZONE_MULTICAST_ADDRS],
  1346. TLAP_ADDR_LEN - TLAP_MCAST_HDR_LEN);
  1347. break;
  1348. default:
  1349. DBGBRK(DBG_LEVEL_FATAL);
  1350. KeBugCheck(0);
  1351. }
  1352. }
  1353. /*** AtalkZipGetNetworkInfoForNode
  1354. *
  1355. */
  1356. BOOLEAN
  1357. AtalkZipGetNetworkInfoForNode(
  1358. IN PPORT_DESCRIPTOR pPortDesc,
  1359. IN PATALK_NODEADDR pNode,
  1360. IN BOOLEAN FindDefZone
  1361. )
  1362. {
  1363. PBUFFER_DESC pBuffDesc = NULL;
  1364. ATALK_ADDR SrcAddr, DstAddr;
  1365. ATALK_ERROR error;
  1366. USHORT NumReqs, DgLen;
  1367. BYTE DgCopy[ZIP_ZONENAME_OFF + MAX_ZONE_LENGTH];
  1368. KIRQL OldIrql;
  1369. BOOLEAN RetCode, Done;
  1370. SEND_COMPL_INFO SendInfo;
  1371. ASSERT(EXT_NET(pPortDesc));
  1372. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1373. if (FindDefZone)
  1374. {
  1375. pPortDesc->pd_Flags &= ~PD_VALID_DEFAULT_ZONE;
  1376. pPortDesc->pd_Flags |= PD_FINDING_DEFAULT_ZONE;
  1377. }
  1378. else
  1379. {
  1380. pPortDesc->pd_Flags &= ~PD_VALID_DESIRED_ZONE;
  1381. pPortDesc->pd_Flags |= PD_FINDING_DESIRED_ZONE;
  1382. }
  1383. // Get source and destination addresses
  1384. SrcAddr.ata_Network = pNode->atn_Network;
  1385. SrcAddr.ata_Node = pNode->atn_Node;
  1386. SrcAddr.ata_Socket = ZONESINFORMATION_SOCKET;
  1387. DstAddr.ata_Network = CABLEWIDE_BROADCAST_NETWORK;
  1388. DstAddr.ata_Node = ATALK_BROADCAST_NODE;
  1389. DstAddr.ata_Socket = ZONESINFORMATION_SOCKET;
  1390. // Build a ZipNetGetInfo datagram
  1391. DgCopy[ZIP_CMD_OFF] = ZIP_GET_NETINFO;
  1392. DgCopy[ZIP_FLAGS_OFF] = 0;
  1393. PUTSHORT2SHORT(DgCopy + ZIP_CABLE_RANGE_START_OFF, 0);
  1394. PUTSHORT2SHORT(DgCopy + ZIP_CABLE_RANGE_END_OFF, 0);
  1395. DgLen = ZIP_ZONENAME_OFF;
  1396. DgCopy[ZIP_ZONELEN_OFF] = 0;
  1397. if (!FindDefZone &&
  1398. (pPortDesc->pd_InitialDesiredZone != NULL))
  1399. {
  1400. DgCopy[ZIP_ZONELEN_OFF] = pPortDesc->pd_InitialDesiredZone->zn_ZoneLen;
  1401. RtlCopyMemory(DgCopy + ZIP_ZONENAME_OFF,
  1402. pPortDesc->pd_InitialDesiredZone->zn_Zone,
  1403. pPortDesc->pd_InitialDesiredZone->zn_ZoneLen);
  1404. DgLen += DgCopy[ZIP_ZONELEN_OFF];
  1405. }
  1406. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1407. for (NumReqs = 0;
  1408. NumReqs < ZIP_NUM_GETNET_INFOS;
  1409. NumReqs++)
  1410. {
  1411. Done = FindDefZone ?
  1412. ((pPortDesc->pd_Flags & PD_VALID_DEFAULT_ZONE) != 0) :
  1413. ((pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE) != 0);
  1414. if (Done)
  1415. {
  1416. break;
  1417. }
  1418. if ((pBuffDesc = AtalkAllocBuffDesc(NULL, DgLen,
  1419. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  1420. {
  1421. break;
  1422. }
  1423. RtlCopyMemory(pBuffDesc->bd_CharBuffer, DgCopy, DgLen);
  1424. // Set the length in the buffer descriptor.
  1425. AtalkSetSizeOfBuffDescData(pBuffDesc, DgLen);
  1426. SendInfo.sc_TransmitCompletion = atalkZipSendComplete;
  1427. SendInfo.sc_Ctx1 = pBuffDesc;
  1428. // SendInfo.sc_Ctx2 = NULL;
  1429. // SendInfo.sc_Ctx3 = NULL;
  1430. error = AtalkDdpTransmit(pPortDesc,
  1431. &SrcAddr,
  1432. &DstAddr,
  1433. DDPPROTO_ZIP,
  1434. pBuffDesc,
  1435. NULL,
  1436. 0,
  1437. 0,
  1438. NULL,
  1439. NULL,
  1440. &SendInfo);
  1441. if (!ATALK_SUCCESS(error))
  1442. {
  1443. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1444. ("AtalkZipGetNetworkInfoForNode: AtalkDdpTransmit %ld\n", error));
  1445. break;
  1446. }
  1447. pBuffDesc = NULL;
  1448. AtalkSleep(ZIP_GET_NETINFO_WAIT);
  1449. }
  1450. if (pBuffDesc != NULL)
  1451. AtalkFreeBuffDesc(pBuffDesc);
  1452. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1453. if (FindDefZone)
  1454. {
  1455. pPortDesc->pd_Flags &= ~PD_FINDING_DEFAULT_ZONE;
  1456. }
  1457. else
  1458. {
  1459. pPortDesc->pd_Flags &= ~PD_FINDING_DESIRED_ZONE;
  1460. }
  1461. RetCode = FindDefZone ?
  1462. ((pPortDesc->pd_Flags & PD_VALID_DEFAULT_ZONE) == PD_VALID_DEFAULT_ZONE) :
  1463. ((pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE) == PD_VALID_DESIRED_ZONE);
  1464. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1465. return RetCode;
  1466. }
  1467. /*** AtalkZipGetMyZone
  1468. *
  1469. */
  1470. ATALK_ERROR
  1471. AtalkZipGetMyZone(
  1472. IN PPORT_DESCRIPTOR pPortDesc,
  1473. IN BOOLEAN fDesired,
  1474. IN OUT PAMDL pAMdl,
  1475. IN INT Size,
  1476. IN PACTREQ pActReq
  1477. )
  1478. {
  1479. PZIPCOMPLETIONINFO pZci = NULL;
  1480. ATALK_ERROR Status = ATALK_NO_ERROR;
  1481. ULONG BytesCopied;
  1482. PZONE pZone;
  1483. KIRQL OldIrql;
  1484. BOOLEAN Done = FALSE;
  1485. ASSERT (VALID_ACTREQ(pActReq));
  1486. if (Size < (MAX_ZONE_LENGTH + 1))
  1487. return ATALK_BUFFER_TOO_SMALL;
  1488. do
  1489. {
  1490. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1491. // For extended network, we either know or cannot find out
  1492. if (EXT_NET(pPortDesc))
  1493. {
  1494. BOOLEAN Yes = FALSE;
  1495. if (fDesired && (pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE))
  1496. {
  1497. pZone = pPortDesc->pd_DesiredZone;
  1498. Yes = TRUE;
  1499. }
  1500. else if (!fDesired && (pPortDesc->pd_Flags & PD_VALID_DEFAULT_ZONE))
  1501. {
  1502. pZone = pPortDesc->pd_DefaultZone;
  1503. Yes = TRUE;
  1504. }
  1505. if (Yes)
  1506. {
  1507. TdiCopyBufferToMdl( pZone->zn_Zone,
  1508. 0,
  1509. pZone->zn_ZoneLen,
  1510. pAMdl,
  1511. 0,
  1512. &BytesCopied);
  1513. ASSERT (BytesCopied == pZone->zn_ZoneLen);
  1514. TdiCopyBufferToMdl( "",
  1515. 0,
  1516. 1,
  1517. pAMdl,
  1518. pZone->zn_ZoneLen,
  1519. &BytesCopied);
  1520. ASSERT (BytesCopied == 1);
  1521. Done = TRUE;
  1522. }
  1523. }
  1524. // For non-extended networks, we need to ask a router. If we don't
  1525. // know about a router, return.
  1526. if (!Done &&
  1527. (EXT_NET(pPortDesc) ||
  1528. !(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY)))
  1529. {
  1530. TdiCopyBufferToMdl( "*",
  1531. 0,
  1532. sizeof("*"),
  1533. pAMdl,
  1534. 0,
  1535. &BytesCopied);
  1536. ASSERT (BytesCopied == sizeof("*"));
  1537. Done = TRUE;
  1538. }
  1539. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1540. if (Done)
  1541. {
  1542. (*pActReq->ar_Completion)(ATALK_NO_ERROR, pActReq);
  1543. break;
  1544. }
  1545. ASSERT (!EXT_NET(pPortDesc));
  1546. // Allocate a Completion info structure
  1547. if ((pZci = AtalkAllocMemory(sizeof(ZIPCOMPLETIONINFO))) == NULL)
  1548. {
  1549. Status = ATALK_RESR_MEM;
  1550. break;
  1551. }
  1552. // Initialize completion info
  1553. #if DBG
  1554. pZci->zci_Signature = ZCI_SIGNATURE;
  1555. #endif
  1556. INITIALIZE_SPIN_LOCK(&pZci->zci_Lock);
  1557. pZci->zci_RefCount = 1;
  1558. pZci->zci_pPortDesc = pPortDesc;
  1559. pZci->zci_pDdpAddr = NULL;
  1560. pZci->zci_pAMdl = pAMdl;
  1561. pZci->zci_BufLen = Size;
  1562. pZci->zci_pActReq = pActReq;
  1563. pZci->zci_Router.ata_Network = pPortDesc->pd_ARouter.atn_Network;
  1564. pZci->zci_Router.ata_Node = pPortDesc->pd_ARouter.atn_Node;
  1565. pZci->zci_Router.ata_Socket = ZONESINFORMATION_SOCKET;
  1566. pZci->zci_ExpirationCount = ZIP_GET_ZONEINFO_RETRIES;
  1567. pZci->zci_NextZoneOff = 0;
  1568. pZci->zci_ZoneCount = -1;
  1569. pZci->zci_AtpRequestType = ZIP_GET_MY_ZONE;
  1570. pZci->zci_Handler = atalkZipGetMyZoneReply;
  1571. AtalkTimerInitialize(&pZci->zci_Timer,
  1572. atalkZipZoneInfoTimer,
  1573. ZIP_GET_ZONEINFO_TIMER);
  1574. Status = atalkZipSendPacket(pZci, TRUE);
  1575. if (!ATALK_SUCCESS(Status))
  1576. {
  1577. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1578. ("AtalkZipGetMyZone: atalkZipSendPacket %ld\n",
  1579. Status));
  1580. pZci->zci_FinalStatus = Status;
  1581. atalkZipDereferenceZci(pZci);
  1582. Status = ATALK_PENDING; // atalkZipDereferenceZci completes the req
  1583. }
  1584. } while (FALSE);
  1585. return(Status);
  1586. }
  1587. /*** atalkZipGetMyZoneReply
  1588. *
  1589. */
  1590. VOID
  1591. atalkZipGetMyZoneReply(
  1592. IN PPORT_DESCRIPTOR pPortDesc,
  1593. IN PDDP_ADDROBJ pDdpAddr,
  1594. IN PBYTE pPkt,
  1595. IN USHORT PktLen,
  1596. IN PATALK_ADDR pSrcAddr,
  1597. IN PATALK_ADDR pDstAddr,
  1598. IN ATALK_ERROR Status,
  1599. IN BYTE DdpType,
  1600. IN PZIPCOMPLETIONINFO pZci,
  1601. IN BOOLEAN OptimizePath,
  1602. IN PVOID OptimizeCtx
  1603. )
  1604. {
  1605. ULONG BytesCopied;
  1606. KIRQL OldIrql;
  1607. USHORT ZoneCnt;
  1608. BYTE ZoneLen;
  1609. do
  1610. {
  1611. if (Status == ATALK_SOCKET_CLOSED)
  1612. {
  1613. pZci->zci_pDdpAddr = NULL;
  1614. if (AtalkTimerCancelEvent(&pZci->zci_Timer, NULL))
  1615. atalkZipDereferenceZci(pZci);
  1616. pZci->zci_FinalStatus = Status;
  1617. atalkZipDereferenceZci(pZci);
  1618. break;
  1619. }
  1620. if ((Status != ATALK_NO_ERROR) ||
  1621. (DdpType != DDPPROTO_ATP) ||
  1622. (PktLen <= ATP_ZIP_FIRST_ZONE_OFF))
  1623. {
  1624. AtalkLogBadPacket(pPortDesc,
  1625. pSrcAddr,
  1626. pDstAddr,
  1627. pPkt,
  1628. PktLen);
  1629. break;
  1630. }
  1631. // We should have one zone
  1632. GETSHORT2SHORT(&ZoneCnt, pPkt + ATP_ZIP_ZONE_CNT_OFF);
  1633. ZoneLen = pPkt[ATP_ZIP_FIRST_ZONE_OFF];
  1634. if ((ZoneCnt != 1) ||
  1635. (ZoneLen == 0) || (ZoneLen > MAX_ZONE_LENGTH))
  1636. {
  1637. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1638. ("atalkZipGetMyZoneReply: Bad reply\n"));
  1639. break;
  1640. }
  1641. if (AtalkTimerCancelEvent(&pZci->zci_Timer, NULL))
  1642. {
  1643. atalkZipDereferenceZci(pZci);
  1644. }
  1645. ACQUIRE_SPIN_LOCK(&pZci->zci_Lock, &OldIrql);
  1646. TdiCopyBufferToMdl( pPkt + ATP_ZIP_FIRST_ZONE_OFF + 1,
  1647. 0,
  1648. ZoneLen,
  1649. pZci->zci_pAMdl,
  1650. 0,
  1651. &BytesCopied);
  1652. ASSERT (BytesCopied == ZoneLen);
  1653. TdiCopyBufferToMdl( "",
  1654. 0,
  1655. 1,
  1656. pZci->zci_pAMdl,
  1657. ZoneLen,
  1658. &BytesCopied);
  1659. ASSERT (BytesCopied == 1);
  1660. pZci->zci_FinalStatus = ATALK_NO_ERROR;
  1661. RELEASE_SPIN_LOCK(&pZci->zci_Lock, OldIrql);
  1662. atalkZipDereferenceZci(pZci);
  1663. } while (FALSE);
  1664. }
  1665. /*** AtalkZipGetZoneList
  1666. *
  1667. */
  1668. ATALK_ERROR
  1669. AtalkZipGetZoneList(
  1670. IN PPORT_DESCRIPTOR pPortDesc,
  1671. IN BOOLEAN fLocalZones,
  1672. IN OUT PAMDL pAMdl,
  1673. IN INT Size,
  1674. IN PACTREQ pActReq
  1675. )
  1676. {
  1677. PZIPCOMPLETIONINFO pZci = NULL;
  1678. ATALK_ERROR Status = ATALK_NO_ERROR;
  1679. ULONG BytesCopied, index, NumZones;
  1680. KIRQL OldIrql;
  1681. BOOLEAN Done = FALSE, PortLocked = TRUE;
  1682. ASSERT (VALID_ACTREQ(pActReq));
  1683. if (Size < (MAX_ZONE_LENGTH + 1))
  1684. return ATALK_BUFFER_TOO_SMALL;
  1685. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1686. do
  1687. {
  1688. // If we don't know about a router, return.
  1689. if (!(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY))
  1690. {
  1691. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_WARN,
  1692. ("AtalkZipGetZoneList: Don't know a router !!!\n"));
  1693. TdiCopyBufferToMdl( "*",
  1694. 0,
  1695. sizeof("*"),
  1696. pAMdl,
  1697. 0,
  1698. &BytesCopied);
  1699. ASSERT (BytesCopied == sizeof("*"));
  1700. Done = TRUE;
  1701. }
  1702. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1703. PortLocked = FALSE;
  1704. if (Done)
  1705. {
  1706. ((PZIP_GETZONELIST_PARAMS)(pActReq->ar_pParms))->ZonesAvailable = 1;
  1707. (*pActReq->ar_Completion)(ATALK_NO_ERROR, pActReq);
  1708. break;
  1709. }
  1710. // If we are a router, then simply copy the zones. Else send a
  1711. // a request to the router. DO NOT SEND A REQUEST IF WE ARE A
  1712. // ROUTER SINCE THAT WILL RESULT IN A HORRIBLE RECURSION RESULTING
  1713. // IN A DOUBLE FAULT (OUT OF STACK SPACE).
  1714. if (pPortDesc->pd_Flags & PD_ROUTER_RUNNING)
  1715. {
  1716. PZONE pZone;
  1717. NumZones = 0;
  1718. if (fLocalZones)
  1719. {
  1720. PZONE_LIST pZoneList;
  1721. // For GetLocalZones, we only want to count zones
  1722. // that are on the network that is directly connected
  1723. // to the port on which the request originated
  1724. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1725. for (index = 0, pZoneList = pPortDesc->pd_ZoneList;
  1726. pZoneList != NULL;
  1727. pZoneList = pZoneList->zl_Next)
  1728. {
  1729. pZone = pZoneList->zl_pZone;
  1730. ASSERT (pZone != NULL);
  1731. // If this packet cannot hold more, we're done
  1732. if ((INT)(index + pZone->zn_ZoneLen + 1) >= Size)
  1733. {
  1734. break;
  1735. }
  1736. // Place zone name in the packet
  1737. TdiCopyBufferToMdl( pZone->zn_Zone,
  1738. 0,
  1739. pZone->zn_ZoneLen + 1,
  1740. pAMdl,
  1741. index,
  1742. &BytesCopied);
  1743. ASSERT (BytesCopied == (ULONG)(pZone->zn_ZoneLen + 1));
  1744. NumZones ++;
  1745. index += (pZone->zn_ZoneLen + 1);
  1746. }
  1747. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1748. Status = (pZoneList != NULL) ?
  1749. ATALK_BUFFER_TOO_SMALL : ATALK_NO_ERROR;
  1750. }
  1751. else
  1752. {
  1753. BOOLEAN PktFull = FALSE;
  1754. INT i;
  1755. ACQUIRE_SPIN_LOCK(&AtalkZoneLock, &OldIrql);
  1756. for (i = 0, index = 0, PktFull = FALSE;
  1757. (i < NUM_ZONES_HASH_BUCKETS) && !PktFull;
  1758. i++)
  1759. {
  1760. for (pZone = AtalkZonesTable[i];
  1761. pZone != NULL;
  1762. pZone = pZone->zn_Next)
  1763. {
  1764. // If this packet cannot hold more, we're done
  1765. if ((INT)(index + pZone->zn_ZoneLen + 1) >= Size)
  1766. {
  1767. PktFull = TRUE;
  1768. break;
  1769. }
  1770. // Place zone name in the packet
  1771. TdiCopyBufferToMdl( pZone->zn_Zone,
  1772. 0,
  1773. pZone->zn_ZoneLen + 1,
  1774. pAMdl,
  1775. index,
  1776. &BytesCopied);
  1777. ASSERT (BytesCopied == (ULONG)(pZone->zn_ZoneLen + 1));
  1778. NumZones ++;
  1779. index += (pZone->zn_ZoneLen + 1);
  1780. }
  1781. }
  1782. RELEASE_SPIN_LOCK(&AtalkZoneLock, OldIrql);
  1783. Status = ((pZone != NULL) || ( i < NUM_ZONES_HASH_BUCKETS)) ?
  1784. ATALK_BUFFER_TOO_SMALL : ATALK_NO_ERROR;
  1785. }
  1786. ((PZIP_GETZONELIST_PARAMS)
  1787. (pActReq->ar_pParms))->ZonesAvailable = NumZones;
  1788. if (ATALK_SUCCESS(Status))
  1789. {
  1790. (*pActReq->ar_Completion)(Status, pActReq);
  1791. }
  1792. break;
  1793. }
  1794. ASSERT ((pPortDesc->pd_Flags & PD_ROUTER_RUNNING) == 0);
  1795. // Allocate a Completion info structure
  1796. if ((pZci = AtalkAllocMemory(sizeof(ZIPCOMPLETIONINFO))) == NULL)
  1797. {
  1798. Status = ATALK_RESR_MEM;
  1799. break;
  1800. }
  1801. // Initialize completion info
  1802. #if DBG
  1803. pZci->zci_Signature = ZCI_SIGNATURE;
  1804. #endif
  1805. INITIALIZE_SPIN_LOCK(&pZci->zci_Lock);
  1806. pZci->zci_RefCount = 1;
  1807. pZci->zci_pPortDesc = pPortDesc;
  1808. pZci->zci_pDdpAddr = NULL;
  1809. pZci->zci_pAMdl = pAMdl;
  1810. pZci->zci_BufLen = Size;
  1811. pZci->zci_pActReq = pActReq;
  1812. pZci->zci_Router.ata_Network = pPortDesc->pd_ARouter.atn_Network;
  1813. pZci->zci_Router.ata_Node = pPortDesc->pd_ARouter.atn_Node;
  1814. pZci->zci_Router.ata_Socket = ZONESINFORMATION_SOCKET;
  1815. pZci->zci_ExpirationCount = ZIP_GET_ZONEINFO_RETRIES;
  1816. pZci->zci_NextZoneOff = 0;
  1817. pZci->zci_ZoneCount = 0;
  1818. pZci->zci_AtpRequestType = ZIP_GET_ZONE_LIST;
  1819. AtalkTimerInitialize(&pZci->zci_Timer,
  1820. atalkZipZoneInfoTimer,
  1821. ZIP_GET_ZONEINFO_TIMER);
  1822. if (fLocalZones)
  1823. pZci->zci_AtpRequestType = ZIP_GET_LOCAL_ZONES;
  1824. pZci->zci_Handler = atalkZipGetZoneListReply;
  1825. Status = atalkZipSendPacket(pZci, TRUE);
  1826. if (!ATALK_SUCCESS(Status))
  1827. {
  1828. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1829. ("AtalkZipGetZoneList: atalkZipSendPacket %ld\n", Status));
  1830. pZci->zci_FinalStatus = Status;
  1831. atalkZipDereferenceZci(pZci);
  1832. Status = ATALK_PENDING; // atalkZipDereferenceZci completes the req
  1833. }
  1834. } while (FALSE);
  1835. if (PortLocked)
  1836. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1837. return(Status);
  1838. }
  1839. /*** atalkZipGetZoneListReply
  1840. *
  1841. */
  1842. VOID
  1843. atalkZipGetZoneListReply(
  1844. IN PPORT_DESCRIPTOR pPortDesc,
  1845. IN PDDP_ADDROBJ pDdpAddr,
  1846. IN PBYTE pPkt,
  1847. IN USHORT PktLen,
  1848. IN PATALK_ADDR pSrcAddr,
  1849. IN PATALK_ADDR pDstAddr,
  1850. IN ATALK_ERROR Status,
  1851. IN BYTE DdpType,
  1852. IN PZIPCOMPLETIONINFO pZci,
  1853. IN BOOLEAN OptimizePath,
  1854. IN PVOID OptimizeCtx
  1855. )
  1856. {
  1857. PBYTE pZone;
  1858. ULONG dindex;
  1859. ULONG BytesCopied;
  1860. USHORT ZoneCnt;
  1861. BYTE ZoneLen;
  1862. BOOLEAN LastFlag, Overflow = FALSE;
  1863. ASSERT(VALID_ZCI(pZci));
  1864. do
  1865. {
  1866. if (Status == ATALK_SOCKET_CLOSED)
  1867. {
  1868. pZci->zci_pDdpAddr = NULL;
  1869. if (AtalkTimerCancelEvent(&pZci->zci_Timer, NULL))
  1870. {
  1871. atalkZipDereferenceZci(pZci);
  1872. }
  1873. pZci->zci_FinalStatus = Status;
  1874. atalkZipDereferenceZci(pZci);
  1875. break;
  1876. }
  1877. if ((Status != ATALK_NO_ERROR) ||
  1878. (DdpType != DDPPROTO_ATP) ||
  1879. (PktLen <= ATP_ZIP_FIRST_ZONE_OFF))
  1880. {
  1881. AtalkLogBadPacket(pPortDesc,
  1882. pSrcAddr,
  1883. pDstAddr,
  1884. pPkt,
  1885. PktLen);
  1886. break;
  1887. }
  1888. // We should have a zone list.
  1889. // Cancel the timer. Start it again if we have not got all the zones
  1890. if (AtalkTimerCancelEvent(&pZci->zci_Timer, NULL))
  1891. {
  1892. atalkZipDereferenceZci(pZci);
  1893. }
  1894. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1895. ("atalkZipGetZoneListReply: More zones. Index %d, SizeLeft %d\n",
  1896. pZci->zci_ZoneCount, pZci->zci_BufLen - pZci->zci_NextZoneOff));
  1897. ACQUIRE_SPIN_LOCK_DPC(&pZci->zci_Lock);
  1898. GETSHORT2SHORT(&ZoneCnt, pPkt + ATP_ZIP_ZONE_CNT_OFF);
  1899. LastFlag = FALSE;
  1900. if ((pPkt[ATP_ZIP_LAST_FLAG_OFF] != 0) ||
  1901. (ZoneCnt == 0))
  1902. LastFlag = TRUE;
  1903. dindex = ATP_ZIP_FIRST_ZONE_OFF;
  1904. while (ZoneCnt != 0)
  1905. {
  1906. // Pull out the next zone
  1907. ZoneLen = pPkt[dindex++];
  1908. if ((ZoneLen == 0) ||
  1909. (ZoneLen > MAX_ZONE_LENGTH) ||
  1910. (PktLen < (dindex + ZoneLen)))
  1911. {
  1912. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1913. ("atalkZipGetZoneListReply: Bad Zip reply\n"));
  1914. break;
  1915. }
  1916. pZone = pPkt + dindex;
  1917. dindex += ZoneLen;
  1918. if ((pZci->zci_NextZoneOff + ZoneLen + 1) > pZci->zci_BufLen)
  1919. {
  1920. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1921. ("AtalkZipGetZoneList: Overflow\n"));
  1922. Overflow = TRUE;
  1923. break;
  1924. }
  1925. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1926. ("AtalkZipGetZoneList: Copying a zone (%d, %d)\n",
  1927. pZci->zci_ZoneCount,
  1928. pZci->zci_BufLen - pZci->zci_NextZoneOff));
  1929. TdiCopyBufferToMdl( pZone,
  1930. 0,
  1931. ZoneLen,
  1932. pZci->zci_pAMdl,
  1933. pZci->zci_NextZoneOff,
  1934. &BytesCopied);
  1935. ASSERT (BytesCopied == ZoneLen);
  1936. TdiCopyBufferToMdl( "",
  1937. 0,
  1938. 1,
  1939. pZci->zci_pAMdl,
  1940. pZci->zci_NextZoneOff + ZoneLen,
  1941. &BytesCopied);
  1942. pZci->zci_NextZoneOff += (ZoneLen + 1);
  1943. pZci->zci_ZoneCount ++;
  1944. ZoneCnt --;
  1945. }
  1946. RELEASE_SPIN_LOCK_DPC(&pZci->zci_Lock);
  1947. if (Overflow || LastFlag)
  1948. {
  1949. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1950. ("atalkZipGetZoneListReply: All that we wanted\n"));
  1951. pZci->zci_FinalStatus = ATALK_NO_ERROR;
  1952. if (Overflow)
  1953. pZci->zci_FinalStatus = ATALK_BUFFER_TOO_SMALL;
  1954. ((PZIP_GETZONELIST_PARAMS)
  1955. (pZci->zci_pActReq->ar_pParms))->ZonesAvailable =
  1956. pZci->zci_ZoneCount;
  1957. atalkZipDereferenceZci(pZci);
  1958. }
  1959. else
  1960. {
  1961. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1962. ("atalkZipGetZoneListReply: Sending another packet\n"));
  1963. Status = atalkZipSendPacket(pZci, TRUE);
  1964. if (!ATALK_SUCCESS(Status))
  1965. {
  1966. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  1967. ("AtalkZipGetZoneListReply: atalkZipSendPacket %ld\n", Status));
  1968. pZci->zci_FinalStatus = Status;
  1969. atalkZipDereferenceZci(pZci);
  1970. }
  1971. }
  1972. } while (FALSE);
  1973. }
  1974. /*** atalkZipZoneInfoTimer
  1975. *
  1976. */
  1977. LOCAL LONG FASTCALL
  1978. atalkZipZoneInfoTimer(
  1979. IN PTIMERLIST pTimer,
  1980. IN BOOLEAN TimerShuttingDown
  1981. )
  1982. {
  1983. PZIPCOMPLETIONINFO pZci;
  1984. ATALK_ERROR Status;
  1985. ULONG BytesCopied;
  1986. BOOLEAN Done = FALSE, RestartTimer = FALSE;
  1987. pZci = (PZIPCOMPLETIONINFO)CONTAINING_RECORD(pTimer, ZIPCOMPLETIONINFO, zci_Timer);
  1988. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1989. ("atalkZipZoneInfoTimer: Entered for pZci = %lx\n", pZci));
  1990. ASSERT(VALID_ZCI(pZci));
  1991. do
  1992. {
  1993. ACQUIRE_SPIN_LOCK_DPC(&pZci->zci_Lock);
  1994. if (--(pZci->zci_ExpirationCount) != 0)
  1995. {
  1996. RestartTimer = TRUE;
  1997. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  1998. ("atalkZipZoneInfoTimer: Sending another packet\n", pZci));
  1999. RELEASE_SPIN_LOCK_DPC(&pZci->zci_Lock);
  2000. Status = atalkZipSendPacket(pZci, FALSE);
  2001. if (!ATALK_SUCCESS(Status))
  2002. {
  2003. RestartTimer = FALSE;
  2004. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2005. ("atalkZipZoneInfoTimer: atalkZipSendPacket %ld\n",
  2006. Status));
  2007. pZci->zci_FinalStatus = Status;
  2008. atalkZipDereferenceZci(pZci);
  2009. }
  2010. break;
  2011. }
  2012. if (pZci->zci_AtpRequestType == ZIP_GET_MY_ZONE)
  2013. {
  2014. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2015. ("atalkZipZoneInfoTimer: Completing GetMyZone\n"));
  2016. TdiCopyBufferToMdl("*",
  2017. 0,
  2018. sizeof("*"),
  2019. pZci->zci_pAMdl,
  2020. 0,
  2021. &BytesCopied);
  2022. }
  2023. else // GET_ZONE_LIST
  2024. {
  2025. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2026. ("atalkZipZoneInfoTimer: Completing GetZoneList\n"));
  2027. if ((pZci->zci_ZoneCount == 0) &&
  2028. ((SHORT)(pZci->zci_NextZoneOff + sizeof("*")) < pZci->zci_BufLen))
  2029. {
  2030. pZci->zci_ZoneCount++;
  2031. TdiCopyBufferToMdl("*",
  2032. 0,
  2033. sizeof("*"),
  2034. pZci->zci_pAMdl,
  2035. pZci->zci_NextZoneOff,
  2036. &BytesCopied);
  2037. ASSERT (BytesCopied == sizeof("*"));
  2038. }
  2039. ((PZIP_GETZONELIST_PARAMS)
  2040. (pZci->zci_pActReq->ar_pParms))->ZonesAvailable =
  2041. pZci->zci_ZoneCount;
  2042. }
  2043. RELEASE_SPIN_LOCK_DPC(&pZci->zci_Lock);
  2044. atalkZipDereferenceZci(pZci); // Timer reference
  2045. pZci->zci_FinalStatus = ATALK_NO_ERROR;
  2046. atalkZipDereferenceZci(pZci);
  2047. ASSERT(!RestartTimer);
  2048. } while (FALSE);
  2049. return (RestartTimer ? ATALK_TIMER_REQUEUE : ATALK_TIMER_NO_REQUEUE);
  2050. }
  2051. /*** atalkZipSendPacket
  2052. *
  2053. */
  2054. ATALK_ERROR
  2055. atalkZipSendPacket(
  2056. IN PZIPCOMPLETIONINFO pZci,
  2057. IN BOOLEAN EnqueueTimer
  2058. )
  2059. {
  2060. PBUFFER_DESC pBuffDesc;
  2061. ATALK_ERROR Status;
  2062. ATALK_ADDR DestAddr;
  2063. PBYTE Datagram;
  2064. SEND_COMPL_INFO SendInfo;
  2065. ASSERT (VALID_ZCI(pZci));
  2066. if (pZci->zci_pDdpAddr == NULL)
  2067. {
  2068. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2069. ("atalkZipSendPacket: Opening Ddp Socket\n"));
  2070. // Open a socket for handling replies
  2071. Status = AtalkDdpOpenAddress(pZci->zci_pPortDesc,
  2072. UNKNOWN_SOCKET,
  2073. NULL,
  2074. pZci->zci_Handler,
  2075. pZci,
  2076. 0,
  2077. NULL,
  2078. &pZci->zci_pDdpAddr);
  2079. if (!ATALK_SUCCESS(Status))
  2080. {
  2081. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2082. ("atalkZipSendPacket: AtalkDdpOpenAddress %ld\n", Status));
  2083. return Status;
  2084. }
  2085. // mark the fact that this is an "internal" socket
  2086. pZci->zci_pDdpAddr->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  2087. }
  2088. ASSERT (VALID_DDP_ADDROBJ(pZci->zci_pDdpAddr));
  2089. // Alloc a buffer desciptor for the atp request
  2090. if ((pBuffDesc = AtalkAllocBuffDesc(pZci->zci_Datagram,
  2091. ZIP_GETZONELIST_DDPSIZE,
  2092. BD_CHAR_BUFFER)) == NULL)
  2093. {
  2094. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2095. ("atalkZipSendPacket: Couldn't allocate a buffdesc\n"));
  2096. AtalkDdpCloseAddress(pZci->zci_pDdpAddr, NULL, NULL);
  2097. return ATALK_RESR_MEM;
  2098. }
  2099. // Start the zone info timer
  2100. if (EnqueueTimer)
  2101. {
  2102. KIRQL OldIrql;
  2103. ACQUIRE_SPIN_LOCK(&pZci->zci_Lock, &OldIrql);
  2104. pZci->zci_RefCount ++; // For the timer
  2105. AtalkTimerScheduleEvent(&pZci->zci_Timer);
  2106. RELEASE_SPIN_LOCK(&pZci->zci_Lock, OldIrql);
  2107. }
  2108. // Build the Atp request and send it along
  2109. Datagram = pBuffDesc->bd_CharBuffer;
  2110. Datagram[ATP_CMD_CONTROL_OFF] = ATP_REQUEST;
  2111. Datagram[ATP_BITMAP_OFF] = 1;
  2112. Datagram[ATP_TRANS_ID_OFF] = 0;
  2113. Datagram[ATP_TRANS_ID_OFF+1] = 0;
  2114. Datagram[ATP_ZIP_CMD_OFF] = (BYTE)pZci->zci_AtpRequestType;
  2115. Datagram[ATP_ZIP_CMD_OFF+1] = 0;
  2116. PUTSHORT2SHORT(Datagram + ATP_ZIP_START_INDEX_OFF, pZci->zci_ZoneCount+1);
  2117. // Set the length in the buffer descriptor.
  2118. AtalkSetSizeOfBuffDescData(pBuffDesc, ZIP_GETZONELIST_DDPSIZE);
  2119. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2120. ("atalkZipSendPacket: Sending the packet along\n"));
  2121. DestAddr = pZci->zci_Router;
  2122. SendInfo.sc_TransmitCompletion = atalkZipSendComplete;
  2123. SendInfo.sc_Ctx1 = pBuffDesc;
  2124. // SendInfo.sc_Ctx2 = NULL;
  2125. // SendInfo.sc_Ctx3 = NULL;
  2126. if (!ATALK_SUCCESS(Status = AtalkDdpSend(pZci->zci_pDdpAddr,
  2127. &DestAddr,
  2128. DDPPROTO_ATP,
  2129. FALSE,
  2130. pBuffDesc,
  2131. NULL,
  2132. 0,
  2133. NULL,
  2134. &SendInfo)))
  2135. {
  2136. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2137. ("atalkZipSendPacket: AtalkDdpSend %ld\n", Status));
  2138. AtalkFreeBuffDesc(pBuffDesc);
  2139. if (AtalkTimerCancelEvent(&pZci->zci_Timer, NULL))
  2140. {
  2141. atalkZipDereferenceZci(pZci);
  2142. }
  2143. }
  2144. else Status = ATALK_PENDING;
  2145. return Status;
  2146. }
  2147. /*** atalkZipDereferenceZci
  2148. *
  2149. */
  2150. LOCAL VOID
  2151. atalkZipDereferenceZci(
  2152. IN PZIPCOMPLETIONINFO pZci
  2153. )
  2154. {
  2155. BOOLEAN Done;
  2156. KIRQL OldIrql;
  2157. ASSERT(VALID_ZCI(pZci));
  2158. ACQUIRE_SPIN_LOCK(&pZci->zci_Lock, &OldIrql);
  2159. Done = (--(pZci->zci_RefCount) == 0);
  2160. RELEASE_SPIN_LOCK(&pZci->zci_Lock, OldIrql);
  2161. if (Done)
  2162. {
  2163. if (pZci->zci_pDdpAddr != NULL)
  2164. AtalkDdpCloseAddress(pZci->zci_pDdpAddr, NULL, NULL);
  2165. (*pZci->zci_pActReq->ar_Completion)(pZci->zci_FinalStatus, pZci->zci_pActReq);
  2166. // Unlock the Zip stuff back again, if there are no more pending zip operations
  2167. AtalkUnlockZipIfNecessary();
  2168. AtalkFreeMemory(pZci);
  2169. }
  2170. }
  2171. // We do not want to send too many queries per invocation of the timer. This is to avoid
  2172. // spending too much time within the timer Dpc and also using up all of the Ndis packets
  2173. // and buffers during this.
  2174. #define MAX_QUERIES_PER_INVOCATION 75
  2175. // Structure used by the atalkZipQueryTimer routine
  2176. typedef struct _QueryTimerData
  2177. {
  2178. struct _QueryTimerData * qtd_Next;
  2179. BOOLEAN qtd_SkipThis;
  2180. PBUFFER_DESC qtd_pBuffDesc;
  2181. ATALK_ADDR qtd_DstAddr;
  2182. PDDP_ADDROBJ qtd_pDdpAddr;
  2183. } QTD, *PQTD;
  2184. /*** atalkZipQueryTimer
  2185. *
  2186. * When we are a router and if any of our RTEs do not have a valid zone list, we send
  2187. * out queries to other routers who do.
  2188. */
  2189. LOCAL LONG FASTCALL
  2190. atalkZipQueryTimer(
  2191. IN PTIMERLIST pContext,
  2192. IN BOOLEAN TimerShuttingDown
  2193. )
  2194. {
  2195. PPORT_DESCRIPTOR pPortDesc;
  2196. ATALK_ADDR SrcAddr;
  2197. PRTE pRte;
  2198. PBYTE Datagram;
  2199. PQTD pQtd, pQtdStart = NULL, *ppQtd = &pQtdStart;
  2200. ATALK_ERROR Status;
  2201. int i, j;
  2202. SEND_COMPL_INFO SendInfo;
  2203. if (TimerShuttingDown)
  2204. return ATALK_TIMER_NO_REQUEUE;
  2205. // Go through the routing tables and send out a query to any network
  2206. // that we do not know the zone name of
  2207. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock)
  2208. for (i = 0, j = 0;
  2209. (i < NUM_RTMP_HASH_BUCKETS) && (j <= MAX_QUERIES_PER_INVOCATION);
  2210. i++)
  2211. {
  2212. for (pRte = AtalkRoutingTable[i]; pRte != NULL; pRte = pRte->rte_Next)
  2213. {
  2214. if (pRte->rte_Flags & RTE_ZONELIST_VALID)
  2215. {
  2216. continue;
  2217. }
  2218. // If login is to restrict access to zones over dial up connection
  2219. // put restrictions here
  2220. if (pRte->rte_PortDesc == RasPortDesc)
  2221. {
  2222. continue;
  2223. }
  2224. // Up the count of # of datagrams used. Do need exceed max.
  2225. if (++j >= MAX_QUERIES_PER_INVOCATION)
  2226. break;
  2227. if (((pQtd = AtalkAllocMemory(sizeof(QTD))) == NULL) ||
  2228. ((pQtd->qtd_pBuffDesc = AtalkAllocBuffDesc(NULL,
  2229. ZIP_ONEZONEQUERY_DDPSIZE,
  2230. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL))
  2231. {
  2232. if (pQtd != NULL)
  2233. AtalkFreeMemory(pQtd);
  2234. break;
  2235. }
  2236. *ppQtd = pQtd;
  2237. pQtd->qtd_Next = NULL;
  2238. ppQtd = &pQtd->qtd_Next;
  2239. pQtd->qtd_SkipThis = FALSE;
  2240. Datagram = pQtd->qtd_pBuffDesc->bd_CharBuffer;
  2241. // Build the datagram and send it on its way
  2242. Datagram[ZIP_CMD_OFF] = ZIP_QUERY;
  2243. Datagram[ZIP_NW_CNT_OFF] = 1;
  2244. PUTSHORT2SHORT(Datagram+ZIP_FIRST_NET_OFF,
  2245. pRte->rte_NwRange.anr_FirstNetwork);
  2246. // Compute the source and destination
  2247. SrcAddr.ata_Network = pRte->rte_PortDesc->pd_ARouter.atn_Network;
  2248. SrcAddr.ata_Node = pRte->rte_PortDesc->pd_ARouter.atn_Node;
  2249. SrcAddr.ata_Socket = ZONESINFORMATION_SOCKET;
  2250. pQtd->qtd_DstAddr.ata_Socket = ZONESINFORMATION_SOCKET;
  2251. if (pRte->rte_NumHops == 0)
  2252. {
  2253. pQtd->qtd_DstAddr = SrcAddr;
  2254. }
  2255. else
  2256. {
  2257. pQtd->qtd_DstAddr.ata_Network = pRte->rte_NextRouter.atn_Network;
  2258. pQtd->qtd_DstAddr.ata_Node = pRte->rte_NextRouter.atn_Node;
  2259. }
  2260. // Map source address to the ddp address object (open socket)
  2261. AtalkDdpReferenceByAddr(pRte->rte_PortDesc,
  2262. &SrcAddr,
  2263. &pQtd->qtd_pDdpAddr,
  2264. &Status);
  2265. if (!ATALK_SUCCESS(Status))
  2266. {
  2267. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2268. ("atalkZipQueryTimer: DdpRefByAddr failed for %d.%d\n",
  2269. SrcAddr.ata_Network, SrcAddr.ata_Node));
  2270. pQtd->qtd_pDdpAddr = NULL;
  2271. pQtd->qtd_SkipThis = TRUE;
  2272. }
  2273. }
  2274. }
  2275. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  2276. // We have a bunch of datagrams ready to be fired off.
  2277. // Make it so.
  2278. SendInfo.sc_TransmitCompletion = atalkZipSendComplete;
  2279. // SendInfo.sc_Ctx2 = NULL;
  2280. // SendInfo.sc_Ctx3 = NULL;
  2281. for (pQtd = pQtdStart; pQtd != NULL; pQtd = pQtdStart)
  2282. {
  2283. pQtdStart = pQtd->qtd_Next;
  2284. // Set the length in the buffer descriptor.
  2285. AtalkSetSizeOfBuffDescData(pQtd->qtd_pBuffDesc, ZIP_ONEZONEQUERY_DDPSIZE);
  2286. SendInfo.sc_Ctx1 = pQtd->qtd_pBuffDesc;
  2287. if (pQtd->qtd_SkipThis ||
  2288. !ATALK_SUCCESS(AtalkDdpSend(pQtd->qtd_pDdpAddr,
  2289. &pQtd->qtd_DstAddr,
  2290. DDPPROTO_ZIP,
  2291. FALSE,
  2292. pQtd->qtd_pBuffDesc,
  2293. NULL,
  2294. 0,
  2295. NULL,
  2296. &SendInfo)))
  2297. {
  2298. AtalkFreeBuffDesc(pQtd->qtd_pBuffDesc);
  2299. }
  2300. if (pQtd->qtd_pDdpAddr != NULL)
  2301. AtalkDdpDereferenceDpc(pQtd->qtd_pDdpAddr);
  2302. AtalkFreeMemory(pQtd);
  2303. }
  2304. return ATALK_TIMER_REQUEUE;
  2305. }
  2306. /*** atalkZipGetZoneListForPort
  2307. *
  2308. */
  2309. LOCAL BOOLEAN
  2310. atalkZipGetZoneListForPort(
  2311. IN PPORT_DESCRIPTOR pPortDesc
  2312. )
  2313. {
  2314. PRTE pRte;
  2315. PBUFFER_DESC pBuffDesc = NULL;
  2316. ATALK_ADDR SrcAddr, DstAddr;
  2317. ATALK_ERROR Status;
  2318. KIRQL OldIrql;
  2319. int NumReqs = 0;
  2320. BOOLEAN RetCode = FALSE;
  2321. BYTE MulticastAddr[ELAP_ADDR_LEN];
  2322. SEND_COMPL_INFO SendInfo;
  2323. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  2324. // Similar to RTMP finding out the network number attached to port, our
  2325. // task is to find out the zone list of the network attached to a
  2326. // particular port. We too don't want to mess up a working AppleTalk
  2327. // internet. So, spend a little while doing zone queries to see if the
  2328. // network already has a zone list -- if we find one, use it; else, we
  2329. // had better be a seed router.
  2330. // Set source and destination address
  2331. SrcAddr.ata_Node = pPortDesc->pd_ARouter.atn_Node;
  2332. SrcAddr.ata_Network = pPortDesc->pd_ARouter.atn_Network;
  2333. SrcAddr.ata_Socket = ZONESINFORMATION_SOCKET;
  2334. DstAddr.ata_Network = CABLEWIDE_BROADCAST_NETWORK;
  2335. DstAddr.ata_Node = ATALK_BROADCAST_NODE;
  2336. DstAddr.ata_Socket = ZONESINFORMATION_SOCKET;
  2337. if ((pRte = AtalkRtmpReferenceRte(pPortDesc->pd_NetworkRange.anr_FirstNetwork)) == NULL)
  2338. {
  2339. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2340. ("atalkZipGetZoneListForPort: Could not reference Rte for nwrange on port\n"));
  2341. return FALSE;
  2342. }
  2343. // Blast a few queries and see if anybody knows our zone-name
  2344. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  2345. pPortDesc->pd_Flags |= PD_FINDING_DEFAULT_ZONE;
  2346. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  2347. SendInfo.sc_TransmitCompletion = atalkZipSendComplete;
  2348. // SendInfo.sc_Ctx2 = NULL;
  2349. // SendInfo.sc_Ctx3 = NULL;
  2350. while ((NumReqs < (ZIP_NUM_QUERIES * ZIP_NUM_RETRIES)) &&
  2351. !(pRte->rte_Flags & RTE_ZONELIST_VALID))
  2352. {
  2353. if ((NumReqs % ZIP_NUM_RETRIES) == 0)
  2354. {
  2355. if ((pBuffDesc = AtalkAllocBuffDesc(NULL, ZIP_ONEZONEQUERY_DDPSIZE,
  2356. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  2357. {
  2358. break;
  2359. }
  2360. pBuffDesc->bd_CharBuffer[ZIP_CMD_OFF] = ZIP_QUERY;
  2361. pBuffDesc->bd_CharBuffer[ZIP_NW_CNT_OFF] = 1;
  2362. PUTSHORT2SHORT(pBuffDesc->bd_CharBuffer + ZIP_FIRST_NET_OFF,
  2363. pPortDesc->pd_NetworkRange.anr_FirstNetwork);
  2364. // Set the length in the buffer descriptor.
  2365. AtalkSetSizeOfBuffDescData(pBuffDesc, ZIP_ONEZONEQUERY_DDPSIZE);
  2366. SendInfo.sc_Ctx1 = pBuffDesc;
  2367. Status = AtalkDdpTransmit(pPortDesc,
  2368. &SrcAddr,
  2369. &DstAddr,
  2370. DDPPROTO_ZIP,
  2371. pBuffDesc,
  2372. NULL,
  2373. 0,
  2374. 0,
  2375. NULL,
  2376. NULL,
  2377. &SendInfo);
  2378. if (!ATALK_SUCCESS(Status))
  2379. {
  2380. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2381. ("atalkZipGetZoneListForPort: AtalkDdpTransmit %ld\n", Status));
  2382. break;
  2383. }
  2384. pBuffDesc = NULL;
  2385. }
  2386. NumReqs++;
  2387. AtalkSleep(ZIP_QUERY_WAIT);
  2388. }
  2389. // We either got an answer or we did not. In the latter case we should
  2390. // be seeding.
  2391. do
  2392. {
  2393. if (pRte->rte_Flags & RTE_ZONELIST_VALID)
  2394. {
  2395. // We got an answer. The valid zone list is in the routing table
  2396. // Move it to the port descriptor
  2397. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  2398. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  2399. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2400. ("atalkZipGetZoneListForPort: Moving ZoneList from Rte to Port %Z\n",
  2401. &pPortDesc->pd_AdapterKey));
  2402. pPortDesc->pd_ZoneList = AtalkZoneCopyList(pRte->rte_ZoneList);
  2403. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  2404. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  2405. if (pPortDesc->pd_ZoneList == NULL)
  2406. {
  2407. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2408. ("atalkZipGetZoneListForPort: Failed to Move ZoneList from Rte to Port\n"));
  2409. break;
  2410. }
  2411. // If this is an extended network, we should already have "ThisZone"
  2412. // set (due to GetNetInfo's when we allocated this node), if not
  2413. // find out the true default zone
  2414. if (EXT_NET(pPortDesc))
  2415. {
  2416. PDDP_ADDROBJ pDdpAddr = NULL;
  2417. ATALK_ADDR Addr;
  2418. ATALK_ERROR Status;
  2419. // The router's Zip packet handler doesn't want to be told
  2420. // about zones (it thinks it knows), so it ignores
  2421. // NetInfoReplies. Switch back to the non-router Zip handler
  2422. // while we do a GetNetworkInfoForNode
  2423. Addr.ata_Node = pPortDesc->pd_ARouter.atn_Node;
  2424. Addr.ata_Network = pPortDesc->pd_ARouter.atn_Network;
  2425. Addr.ata_Socket = ZONESINFORMATION_SOCKET;
  2426. AtalkDdpReferenceByAddr(pPortDesc, &Addr, &pDdpAddr, &Status);
  2427. if (!ATALK_SUCCESS(Status))
  2428. {
  2429. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  2430. ("atalkZipGetZoneListForPort: AtalkDdpRefByAddr %ld for %d.%d\n",
  2431. Status, Addr.ata_Network, Addr.ata_Node));
  2432. break;
  2433. }
  2434. AtalkDdpNewHandlerForSocket(pDdpAddr,
  2435. AtalkZipPacketIn,
  2436. pPortDesc);
  2437. if ((!(pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE) &&
  2438. !AtalkZipGetNetworkInfoForNode(pPortDesc,
  2439. &pPortDesc->pd_ARouter,
  2440. FALSE)) ||
  2441. !AtalkZipGetNetworkInfoForNode(pPortDesc,
  2442. &pPortDesc->pd_ARouter,
  2443. TRUE))
  2444. {
  2445. AtalkDdpDereference(pDdpAddr);
  2446. break;
  2447. }
  2448. // Switch back the handler to the router's version
  2449. AtalkDdpNewHandlerForSocket(pDdpAddr,
  2450. AtalkZipPacketInRouter,
  2451. pPortDesc);
  2452. AtalkDdpDereference(pDdpAddr);
  2453. // The default zone had better be on the list we just
  2454. // received
  2455. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  2456. if (!AtalkZoneOnList(pPortDesc->pd_DefaultZone,
  2457. pPortDesc->pd_ZoneList) ||
  2458. !AtalkZoneOnList(pPortDesc->pd_DesiredZone,
  2459. pPortDesc->pd_ZoneList))
  2460. {
  2461. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2462. ("atalkZipGetZoneListForPort: Ext port, Default/Desired zone not on list\n"));
  2463. }
  2464. else RetCode = TRUE;
  2465. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  2466. }
  2467. else
  2468. {
  2469. // On non-extended network, the one entry on the zone list
  2470. // should also be "ThisZone"
  2471. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  2472. if (pPortDesc->pd_DesiredZone != NULL)
  2473. AtalkZoneDereference(pPortDesc->pd_DesiredZone);
  2474. AtalkZoneReferenceByPtr(pPortDesc->pd_DesiredZone =
  2475. pPortDesc->pd_ZoneList->zl_pZone);
  2476. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  2477. RetCode = TRUE;
  2478. }
  2479. break;
  2480. }
  2481. // We did not get an answer. We had better be able to seed. There is
  2482. // a chance that we got "ThisZone" set when allocating our node and
  2483. // whatever router told us that went down before we could ask for the
  2484. // zone list - so de-allocate the multicast address, if any first
  2485. if ((pPortDesc->pd_Flags & (PD_EXT_NET | PD_VALID_DESIRED_ZONE)) ==
  2486. (PD_EXT_NET | PD_VALID_DESIRED_ZONE))
  2487. {
  2488. if (!AtalkFixedCompareCaseSensitive(pPortDesc->pd_ZoneMulticastAddr,
  2489. pPortDesc->pd_BroadcastAddrLen,
  2490. pPortDesc->pd_BroadcastAddr,
  2491. pPortDesc->pd_BroadcastAddrLen))
  2492. (*pPortDesc->pd_RemoveMulticastAddr)(pPortDesc,
  2493. pPortDesc->pd_ZoneMulticastAddr,
  2494. FALSE,
  2495. NULL,
  2496. NULL);
  2497. }
  2498. // Now we better know enough to seed
  2499. if (pPortDesc->pd_InitialZoneList == NULL)
  2500. {
  2501. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2502. ("atalkZipGetZoneListForPort: %sExt port, NULL InitialZoneList\n",
  2503. EXT_NET(pPortDesc) ? "" : "Non"));
  2504. break;
  2505. }
  2506. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  2507. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2508. ("atalkZipGetZoneListForPort: Moving Initial ZoneList to Current on port %Z\n",
  2509. &pPortDesc->pd_AdapterKey));
  2510. pPortDesc->pd_ZoneList = AtalkZoneCopyList(pPortDesc->pd_InitialZoneList);
  2511. if (EXT_NET(pPortDesc))
  2512. {
  2513. // We need to seed the default zone too
  2514. AtalkZoneReferenceByPtr(pPortDesc->pd_DefaultZone =
  2515. pPortDesc->pd_InitialDefaultZone);
  2516. pPortDesc->pd_Flags |= PD_VALID_DEFAULT_ZONE;
  2517. if (pPortDesc->pd_InitialDesiredZone != NULL)
  2518. {
  2519. AtalkZoneReferenceByPtr(pPortDesc->pd_DesiredZone =
  2520. pPortDesc->pd_InitialDesiredZone);
  2521. }
  2522. else
  2523. {
  2524. AtalkZoneReferenceByPtr(pPortDesc->pd_DesiredZone =
  2525. pPortDesc->pd_InitialDefaultZone);
  2526. }
  2527. // Finally set the zone multicast address
  2528. AtalkZipMulticastAddrForZone(pPortDesc,
  2529. pPortDesc->pd_DesiredZone->zn_Zone,
  2530. pPortDesc->pd_DesiredZone->zn_ZoneLen,
  2531. MulticastAddr);
  2532. if (!AtalkFixedCompareCaseSensitive(MulticastAddr,
  2533. pPortDesc->pd_BroadcastAddrLen,
  2534. pPortDesc->pd_BroadcastAddr,
  2535. pPortDesc->pd_BroadcastAddrLen))
  2536. {
  2537. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  2538. (*pPortDesc->pd_AddMulticastAddr)(pPortDesc,
  2539. MulticastAddr,
  2540. FALSE,
  2541. NULL,
  2542. NULL);
  2543. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  2544. }
  2545. RtlCopyMemory(pPortDesc->pd_ZoneMulticastAddr,
  2546. MulticastAddr,
  2547. pPortDesc->pd_BroadcastAddrLen);
  2548. }
  2549. else
  2550. {
  2551. // On non-extended networks, this (desired/default)should be the
  2552. // only one on zone-list
  2553. AtalkZoneReferenceByPtr(pPortDesc->pd_DesiredZone =
  2554. pPortDesc->pd_ZoneList->zl_pZone);
  2555. }
  2556. pPortDesc->pd_Flags |= PD_VALID_DESIRED_ZONE;
  2557. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  2558. RetCode = TRUE;
  2559. } while (FALSE);
  2560. AtalkRtmpDereferenceRte(pRte, FALSE);
  2561. if (pBuffDesc != NULL)
  2562. {
  2563. AtalkFreeBuffDesc(pBuffDesc);
  2564. }
  2565. return(RetCode);
  2566. }
  2567. /*** AtalkZipZoneReferenceByName
  2568. *
  2569. */
  2570. PZONE
  2571. AtalkZoneReferenceByName(
  2572. IN PBYTE ZoneName,
  2573. IN BYTE ZoneLen
  2574. )
  2575. {
  2576. PZONE pZone;
  2577. BYTE Len;
  2578. KIRQL OldIrql;
  2579. ULONG i, Hash;
  2580. for (i = 0, Hash = 0, Len = ZoneLen;
  2581. Len > 0;
  2582. Len --, i++)
  2583. {
  2584. Hash <<= 1;
  2585. Hash += AtalkUpCaseTable[ZoneName[i]];
  2586. }
  2587. Hash %= NUM_ZONES_HASH_BUCKETS;
  2588. ACQUIRE_SPIN_LOCK(&AtalkZoneLock, &OldIrql);
  2589. for (pZone = AtalkZonesTable[Hash];
  2590. pZone != NULL;
  2591. pZone = pZone->zn_Next)
  2592. {
  2593. if (AtalkFixedCompareCaseInsensitive(ZoneName,
  2594. ZoneLen,
  2595. pZone->zn_Zone,
  2596. pZone->zn_ZoneLen))
  2597. {
  2598. pZone->zn_RefCount ++;
  2599. break;
  2600. }
  2601. }
  2602. if (pZone == NULL)
  2603. {
  2604. if ((pZone = (PZONE)AtalkAllocMemory(sizeof(ZONE) + ZoneLen)) != NULL)
  2605. {
  2606. pZone->zn_RefCount = 1;
  2607. pZone->zn_ZoneLen = ZoneLen;
  2608. RtlCopyMemory(pZone->zn_Zone, ZoneName, ZoneLen);
  2609. pZone->zn_Zone[ZoneLen] = 0;
  2610. AtalkLinkDoubleAtHead(AtalkZonesTable[Hash],
  2611. pZone,
  2612. zn_Next,
  2613. zn_Prev);
  2614. }
  2615. }
  2616. RELEASE_SPIN_LOCK(&AtalkZoneLock, OldIrql);
  2617. return(pZone);
  2618. }
  2619. /*** AtalkZipZoneReferenceByPtr
  2620. *
  2621. */
  2622. VOID
  2623. AtalkZoneReferenceByPtr(
  2624. IN PZONE pZone
  2625. )
  2626. {
  2627. KIRQL OldIrql;
  2628. ACQUIRE_SPIN_LOCK(&AtalkZoneLock, &OldIrql);
  2629. pZone->zn_RefCount++;
  2630. RELEASE_SPIN_LOCK(&AtalkZoneLock, OldIrql);
  2631. }
  2632. /*** AtalkZoneDereference
  2633. *
  2634. */
  2635. VOID
  2636. AtalkZoneDereference(
  2637. IN PZONE pZone
  2638. )
  2639. {
  2640. KIRQL OldIrql;
  2641. ACQUIRE_SPIN_LOCK(&AtalkZoneLock, &OldIrql);
  2642. if (--pZone->zn_RefCount == 0)
  2643. {
  2644. AtalkUnlinkDouble(pZone, zn_Next, zn_Prev);
  2645. AtalkFreeMemory(pZone);
  2646. }
  2647. RELEASE_SPIN_LOCK(&AtalkZoneLock, OldIrql);
  2648. }
  2649. /*** AtalkZipZoneFreeList
  2650. *
  2651. */
  2652. VOID
  2653. AtalkZoneFreeList(
  2654. IN PZONE_LIST pZoneList
  2655. )
  2656. {
  2657. PZONE_LIST pNextZone;
  2658. for (; pZoneList != NULL; pZoneList = pNextZone)
  2659. {
  2660. pNextZone = pZoneList->zl_Next;
  2661. AtalkZoneDereference(pZoneList->zl_pZone);
  2662. AtalkFreeMemory(pZoneList);
  2663. }
  2664. }
  2665. /*** AtalkZoneNameOnList
  2666. *
  2667. */
  2668. BOOLEAN
  2669. AtalkZoneNameOnList(
  2670. IN PBYTE ZoneName,
  2671. IN BYTE ZoneLen,
  2672. IN PZONE_LIST pZoneList
  2673. )
  2674. {
  2675. for ( ; pZoneList != NULL; pZoneList = pZoneList->zl_Next)
  2676. if (AtalkFixedCompareCaseInsensitive(pZoneList->zl_pZone->zn_Zone,
  2677. pZoneList->zl_pZone->zn_ZoneLen,
  2678. ZoneName, ZoneLen))
  2679. return(TRUE);
  2680. return(FALSE);
  2681. }
  2682. /*** AtalkZipZoneOnList
  2683. *
  2684. */
  2685. BOOLEAN
  2686. AtalkZoneOnList(
  2687. IN PZONE pZone,
  2688. IN PZONE_LIST pZoneList
  2689. )
  2690. {
  2691. for ( ; pZoneList != NULL; pZoneList = pZoneList->zl_Next)
  2692. if (pZoneList->zl_pZone == pZone)
  2693. return(TRUE);
  2694. return(FALSE);
  2695. }
  2696. /*** AtalkZipZone
  2697. *
  2698. */
  2699. ULONG
  2700. AtalkZoneNumOnList(
  2701. IN PZONE_LIST pZoneList
  2702. )
  2703. {
  2704. ULONG Cnt;
  2705. for (Cnt = 0; pZoneList != NULL; pZoneList = pZoneList->zl_Next)
  2706. Cnt++;
  2707. return Cnt;
  2708. }
  2709. /*** AtalkZipZoneAddToList
  2710. *
  2711. */
  2712. PZONE_LIST
  2713. AtalkZoneAddToList(
  2714. IN PZONE_LIST pZoneList,
  2715. IN PBYTE ZoneName,
  2716. IN BYTE ZoneLen
  2717. )
  2718. {
  2719. PZONE_LIST pNewZoneList;
  2720. PZONE pZone;
  2721. // Get memory for a new ZoneList node.
  2722. pNewZoneList = (PZONE_LIST)AtalkAllocMemory(sizeof(ZONE_LIST));
  2723. if (pNewZoneList != NULL)
  2724. {
  2725. if ((pZone = AtalkZoneReferenceByName(ZoneName, ZoneLen)) != NULL)
  2726. {
  2727. pNewZoneList->zl_Next = pZoneList;
  2728. pNewZoneList->zl_pZone = pZone;
  2729. }
  2730. else
  2731. {
  2732. AtalkZoneFreeList(pNewZoneList);
  2733. pNewZoneList = NULL;
  2734. }
  2735. }
  2736. else
  2737. {
  2738. AtalkZoneFreeList(pZoneList);
  2739. }
  2740. return(pNewZoneList);
  2741. }
  2742. /*** AtalkZipZoneCopyList
  2743. *
  2744. */
  2745. PZONE_LIST
  2746. AtalkZoneCopyList(
  2747. IN PZONE_LIST pZoneList
  2748. )
  2749. {
  2750. PZONE_LIST pNewZoneList,
  2751. pZoneListStart = NULL,
  2752. *ppZoneList = &pZoneListStart;
  2753. for (; pZoneList != NULL; pZoneList = pZoneList = pZoneList->zl_Next)
  2754. {
  2755. pNewZoneList = AtalkAllocMemory(sizeof(ZONE_LIST));
  2756. if (pNewZoneList == NULL)
  2757. {
  2758. break;
  2759. }
  2760. pNewZoneList->zl_Next = NULL;
  2761. pNewZoneList->zl_pZone = pZoneList->zl_pZone;
  2762. *ppZoneList = pNewZoneList;
  2763. ppZoneList = &pNewZoneList->zl_Next;
  2764. AtalkZoneReferenceByPtr(pNewZoneList->zl_pZone);
  2765. }
  2766. if (pNewZoneList == NULL)
  2767. {
  2768. AtalkZoneFreeList(pZoneListStart);
  2769. }
  2770. return(pZoneListStart);
  2771. }
  2772. /*** atalkZipSendComplete
  2773. *
  2774. */
  2775. VOID FASTCALL
  2776. atalkZipSendComplete(
  2777. IN NDIS_STATUS Status,
  2778. IN PSEND_COMPL_INFO pSendInfo
  2779. )
  2780. {
  2781. PBUFFER_DESC pBuffDesc = (PBUFFER_DESC)(pSendInfo->sc_Ctx1);
  2782. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_INFO,
  2783. ("atalkZipSendComplete: Freeing BuffDesc %lx\n", pBuffDesc));
  2784. if (!ATALK_SUCCESS(Status))
  2785. DBGPRINT(DBG_COMP_ZIP, DBG_LEVEL_ERR,
  2786. ("atalkZipSendComplete: Failed %lx, pBuffDesc %lx\n",
  2787. Status, pBuffDesc));
  2788. AtalkFreeBuffDesc(pBuffDesc);
  2789. }
  2790. #if DBG
  2791. VOID
  2792. AtalkZoneDumpTable(
  2793. VOID
  2794. )
  2795. {
  2796. int i;
  2797. PZONE pZone;
  2798. ACQUIRE_SPIN_LOCK_DPC(&AtalkZoneLock);
  2799. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL, ("ZONETABLE: \n"));
  2800. for (i = 0; i < NUM_ZONES_HASH_BUCKETS; i ++)
  2801. {
  2802. for (pZone = AtalkZonesTable[i]; pZone != NULL; pZone = pZone->zn_Next)
  2803. {
  2804. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  2805. ("\t\t%s\n", pZone->zn_Zone));
  2806. }
  2807. }
  2808. RELEASE_SPIN_LOCK_DPC(&AtalkZoneLock);
  2809. }
  2810. #endif