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

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