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.

1892 lines
51 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. rtmp.c
  5. Abstract:
  6. This module implements the rtmp.
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com)
  9. Nikhil Kamkolkar (nikhilk@microsoft.com)
  10. Revision History:
  11. 26 Feb 1993 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #include <atalk.h>
  15. #pragma hdrstop
  16. #define FILENUM RTMP
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, AtalkRtmpInit)
  19. #pragma alloc_text(PAGEINIT, AtalkInitRtmpStartProcessingOnPort)
  20. #pragma alloc_text(PAGEINIT, atalkRtmpGetOrSetNetworkNumber)
  21. #pragma alloc_text(PAGEINIT, AtalkRtmpKillPortRtes)
  22. #pragma alloc_text(PAGE_RTR, AtalkRtmpPacketInRouter)
  23. #pragma alloc_text(PAGE_RTR, AtalkRtmpReferenceRte)
  24. #pragma alloc_text(PAGE_RTR, AtalkRtmpDereferenceRte)
  25. #pragma alloc_text(PAGE_RTR, atalkRtmpCreateRte)
  26. #pragma alloc_text(PAGE_RTR, atalkRtmpRemoveRte)
  27. #pragma alloc_text(PAGE_RTR, atalkRtmpSendTimer)
  28. #pragma alloc_text(PAGE_RTR, atalkRtmpValidityTimer)
  29. #pragma alloc_text(PAGE_RTR, atalkRtmpSendRoutingData)
  30. #endif
  31. /*** AtalkRtmpInit
  32. *
  33. */
  34. ATALK_ERROR
  35. AtalkRtmpInit(
  36. IN BOOLEAN Init
  37. )
  38. {
  39. if (Init)
  40. {
  41. // Allocate space for routing tables and recent routes
  42. AtalkRoutingTable =
  43. (PRTE *)AtalkAllocZeroedMemory(sizeof(PRTE) * NUM_RTMP_HASH_BUCKETS);
  44. AtalkRecentRoutes =
  45. (PRTE *)AtalkAllocZeroedMemory(sizeof(PRTE) * NUM_RECENT_ROUTES);
  46. if ((AtalkRecentRoutes == NULL) || (AtalkRoutingTable == NULL))
  47. {
  48. if (AtalkRoutingTable != NULL)
  49. {
  50. AtalkFreeMemory(AtalkRoutingTable);
  51. AtalkRoutingTable = NULL;
  52. }
  53. return ATALK_RESR_MEM;
  54. }
  55. INITIALIZE_SPIN_LOCK(&AtalkRteLock);
  56. }
  57. else
  58. {
  59. // At this point, we are unloading and there are no race conditions
  60. // or lock contentions. Do not bother locking down the rtmp tables
  61. if (AtalkRoutingTable != NULL)
  62. {
  63. int i;
  64. PRTE pRte;
  65. for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i++)
  66. {
  67. ASSERT(AtalkRoutingTable[i] == NULL);
  68. }
  69. AtalkFreeMemory(AtalkRoutingTable);
  70. AtalkRoutingTable = NULL;
  71. }
  72. if (AtalkRecentRoutes != NULL)
  73. {
  74. AtalkFreeMemory(AtalkRecentRoutes);
  75. AtalkRecentRoutes = NULL;
  76. }
  77. }
  78. return ATALK_NO_ERROR;
  79. }
  80. BOOLEAN
  81. AtalkInitRtmpStartProcessingOnPort(
  82. IN PPORT_DESCRIPTOR pPortDesc,
  83. IN PATALK_NODEADDR pRouterNode
  84. )
  85. {
  86. ATALK_ADDR closeAddr;
  87. ATALK_ERROR Status;
  88. PRTE pRte;
  89. KIRQL OldIrql;
  90. BOOLEAN rc = FALSE;
  91. PDDP_ADDROBJ pRtDdpAddr=NULL;
  92. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  93. // For extended networks, the process of acquiring the node has done most of the work
  94. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  95. do
  96. {
  97. if (EXT_NET(pPortDesc))
  98. {
  99. if ((pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY) &&
  100. (pPortDesc->pd_InitialNetworkRange.anr_FirstNetwork != UNKNOWN_NETWORK))
  101. {
  102. if (!NW_RANGE_EQUAL(&pPortDesc->pd_InitialNetworkRange,
  103. &pPortDesc->pd_NetworkRange))
  104. {
  105. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  106. ("AtalkRtmpStartProcessingOnPort: Initial range %d-%d, Actual %d-%d\n",
  107. pPortDesc->pd_InitialNetworkRange.anr_FirstNetwork,
  108. pPortDesc->pd_InitialNetworkRange.anr_LastNetwork,
  109. pPortDesc->pd_NetworkRange.anr_FirstNetwork,
  110. pPortDesc->pd_NetworkRange.anr_LastNetwork));
  111. LOG_ERRORONPORT(pPortDesc,
  112. EVENT_ATALK_INVALID_NETRANGE,
  113. 0,
  114. NULL,
  115. 0);
  116. // Change InitialNetwork range so that it matches the net
  117. pPortDesc->pd_InitialNetworkRange = pPortDesc->pd_NetworkRange;
  118. }
  119. }
  120. // We are the seed router, so seed if possible
  121. if (!(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY) &&
  122. !(pPortDesc->pd_Flags & PD_SEED_ROUTER))
  123. {
  124. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  125. break;
  126. }
  127. if (!(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY))
  128. {
  129. pPortDesc->pd_NetworkRange = pPortDesc->pd_InitialNetworkRange;
  130. }
  131. }
  132. // For non-extended network either seed or find our network number
  133. else
  134. {
  135. PATALK_NODE pNode;
  136. USHORT SuggestedNetwork;
  137. int i;
  138. SuggestedNetwork = UNKNOWN_NETWORK;
  139. if (pPortDesc->pd_Flags & PD_SEED_ROUTER)
  140. SuggestedNetwork = pPortDesc->pd_InitialNetworkRange.anr_FirstNetwork;
  141. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  142. if (!atalkRtmpGetOrSetNetworkNumber(pPortDesc, SuggestedNetwork))
  143. {
  144. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  145. ("AtalkRtmpStartProcessingOnPort: atalkRtmpGetOrSetNetworkNumber failed\n"));
  146. break;
  147. }
  148. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  149. if (!(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY))
  150. {
  151. pPortDesc->pd_NetworkRange.anr_FirstNetwork =
  152. pPortDesc->pd_NetworkRange.anr_LastNetwork =
  153. pPortDesc->pd_InitialNetworkRange.anr_FirstNetwork;
  154. }
  155. // We'd have allocated a node with network 0, fix it up. Alas the fixup
  156. // also involves all the sockets so far created on this node.
  157. pNode = pPortDesc->pd_Nodes;
  158. ASSERT((pNode != NULL) && (pPortDesc->pd_RouterNode == pNode));
  159. pNode->an_NodeAddr.atn_Network =
  160. pPortDesc->pd_LtNetwork =
  161. pPortDesc->pd_ARouter.atn_Network =
  162. pRouterNode->atn_Network = pPortDesc->pd_NetworkRange.anr_FirstNetwork;
  163. ACQUIRE_SPIN_LOCK_DPC(&pNode->an_Lock);
  164. for (i = 0; i < NODE_DDPAO_HASH_SIZE; i ++)
  165. {
  166. PDDP_ADDROBJ pDdpAddr;
  167. for (pDdpAddr = pNode->an_DdpAoHash[i];
  168. pDdpAddr != NULL;
  169. pDdpAddr = pDdpAddr->ddpao_Next)
  170. {
  171. ACQUIRE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  172. pDdpAddr->ddpao_Addr.ata_Network =
  173. pPortDesc->pd_NetworkRange.anr_FirstNetwork;
  174. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  175. }
  176. }
  177. RELEASE_SPIN_LOCK_DPC(&pNode->an_Lock);
  178. }
  179. // We're the router now. Mark it appropriately
  180. pPortDesc->pd_Flags |= (PD_ROUTER_RUNNING | PD_SEEN_ROUTER_RECENTLY);
  181. KeSetEvent(&pPortDesc->pd_SeenRouterEvent, IO_NETWORK_INCREMENT, FALSE);
  182. pPortDesc->pd_ARouter = *pRouterNode;
  183. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  184. // Before creating a Rte for ourselves, check if there is an Rte with
  185. // the same network range already. This will happen, for instance, when
  186. // we are routing on ports which other routers are also seeding and we
  187. // got to know of our port from the other router on another port !!!
  188. do
  189. {
  190. pRte = AtalkRtmpReferenceRte(pPortDesc->pd_NetworkRange.anr_FirstNetwork);
  191. if (pRte != NULL)
  192. {
  193. ACQUIRE_SPIN_LOCK(&pRte->rte_Lock, &OldIrql);
  194. pRte->rte_RefCount --; // Take away creation reference
  195. pRte->rte_Flags |= RTE_DELETE;
  196. RELEASE_SPIN_LOCK(&pRte->rte_Lock, OldIrql);
  197. AtalkRtmpDereferenceRte(pRte, FALSE);
  198. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  199. ("AtalkRtmpStartProcessing: Invalid Rte for port %Z's range found\n",
  200. &pPortDesc->pd_AdapterKey));
  201. }
  202. } while (pRte != NULL);
  203. // Now we get to really, really create our own Rte !!!
  204. if (!atalkRtmpCreateRte(pPortDesc->pd_NetworkRange,
  205. pPortDesc,
  206. pRouterNode,
  207. 0))
  208. {
  209. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  210. ("AtalkRtmpStartProcessingOnPort: Could not create Rte\n"));
  211. break;
  212. }
  213. // Switch the incoming rtmp handler to the router version
  214. closeAddr.ata_Network = pRouterNode->atn_Network;
  215. closeAddr.ata_Node = pRouterNode->atn_Node;
  216. closeAddr.ata_Socket = RTMP_SOCKET;
  217. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  218. AtalkDdpInitCloseAddress(pPortDesc, &closeAddr);
  219. Status = AtalkDdpOpenAddress(pPortDesc,
  220. RTMP_SOCKET,
  221. pRouterNode,
  222. AtalkRtmpPacketInRouter,
  223. NULL,
  224. DDPPROTO_ANY,
  225. NULL,
  226. &pRtDdpAddr);
  227. if (!ATALK_SUCCESS(Status))
  228. {
  229. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  230. ("AtalkRtmpStartProcessingOnPort: AtalkDdpOpenAddress failed %ld\n",
  231. Status));
  232. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  233. ("AtalkRtmpStartProcessingOnPort: Unable to open the routers rtmp socket %ld\n",
  234. Status));
  235. break;
  236. }
  237. // mark the fact that this is an "internal" socket
  238. pRtDdpAddr->ddpao_Flags |= DDPAO_SOCK_INTERNAL;
  239. // Start the timers now. Reference the port for each timer.
  240. AtalkPortReferenceByPtr(pPortDesc, &Status);
  241. if (!ATALK_SUCCESS(Status))
  242. {
  243. break;
  244. }
  245. AtalkTimerInitialize(&pPortDesc->pd_RtmpSendTimer,
  246. atalkRtmpSendTimer,
  247. RTMP_SEND_TIMER);
  248. AtalkTimerScheduleEvent(&pPortDesc->pd_RtmpSendTimer);
  249. if (!atalkRtmpVdtTmrRunning)
  250. {
  251. AtalkTimerInitialize(&atalkRtmpVTimer,
  252. atalkRtmpValidityTimer,
  253. RTMP_VALIDITY_TIMER);
  254. AtalkTimerScheduleEvent(&atalkRtmpVTimer);
  255. atalkRtmpVdtTmrRunning = TRUE;
  256. }
  257. rc = TRUE;
  258. } while (FALSE);
  259. return rc;
  260. }
  261. // Private data structure used between AtalkRtmpPacketIn and atalkRtmpGetNwInfo
  262. typedef struct _QueuedGetNwInfo
  263. {
  264. WORK_QUEUE_ITEM qgni_WorkQItem;
  265. PPORT_DESCRIPTOR qgni_pPortDesc;
  266. PDDP_ADDROBJ qgni_pDdpAddr;
  267. ATALK_NODEADDR qgni_SenderNode;
  268. ATALK_NETWORKRANGE qgni_CableRange;
  269. BOOLEAN qgni_FreeThis;
  270. } QGNI, *PQGNI;
  271. VOID
  272. atalkRtmpGetNwInfo(
  273. IN PQGNI pQgni
  274. )
  275. {
  276. PPORT_DESCRIPTOR pPortDesc = pQgni->qgni_pPortDesc;
  277. PDDP_ADDROBJ pDdpAddr = pQgni->qgni_pDdpAddr;
  278. KIRQL OldIrql;
  279. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  280. AtalkZipGetNetworkInfoForNode(pPortDesc,
  281. &pDdpAddr->ddpao_Node->an_NodeAddr,
  282. FALSE);
  283. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  284. if (!(pPortDesc->pd_Flags & PD_ROUTER_RUNNING))
  285. {
  286. // Well, we heard from a router. Copy the information. Don't do it
  287. // if we're a router [maybe a proxy node on arouting port] -- we don't
  288. // want "aRouter" to shift away from "us."
  289. pPortDesc->pd_Flags |= PD_SEEN_ROUTER_RECENTLY;
  290. KeSetEvent(&pPortDesc->pd_SeenRouterEvent, IO_NETWORK_INCREMENT, FALSE);
  291. pPortDesc->pd_LastRouterTime = AtalkGetCurrentTick();
  292. pPortDesc->pd_ARouter = pQgni->qgni_SenderNode;
  293. pPortDesc->pd_NetworkRange = pQgni->qgni_CableRange;
  294. }
  295. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  296. if (pQgni->qgni_FreeThis)
  297. {
  298. AtalkDdpDereference(pDdpAddr);
  299. AtalkFreeMemory(pQgni);
  300. }
  301. }
  302. VOID
  303. AtalkRtmpPacketIn(
  304. IN PPORT_DESCRIPTOR pPortDesc,
  305. IN PDDP_ADDROBJ pDdpAddr,
  306. IN PBYTE pPkt,
  307. IN USHORT PktLen,
  308. IN PATALK_ADDR pSrcAddr,
  309. IN PATALK_ADDR pDstAddr,
  310. IN ATALK_ERROR ErrorCode,
  311. IN BYTE DdpType,
  312. IN PVOID pHandlerCtx,
  313. IN BOOLEAN OptimizedPath,
  314. IN PVOID OptimizeCtx
  315. )
  316. {
  317. ATALK_NODEADDR SenderNode;
  318. ATALK_NETWORKRANGE CableRange;
  319. ATALK_ERROR Status;
  320. TIME TimeS, TimeE, TimeD;
  321. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  322. TimeS = KeQueryPerformanceCounter(NULL);
  323. do
  324. {
  325. if (ErrorCode == ATALK_SOCKET_CLOSED)
  326. break;
  327. else if (ErrorCode != ATALK_NO_ERROR)
  328. {
  329. break;
  330. }
  331. if (DdpType != DDPPROTO_RTMPRESPONSEORDATA)
  332. break;
  333. // we do not care about non-ext tuples on an extended network
  334. if ((EXT_NET(pPortDesc)) && (PktLen < (RTMP_RANGE_END_OFF+2)))
  335. {
  336. break;
  337. }
  338. GETSHORT2SHORT(&SenderNode.atn_Network, pPkt+RTMP_SENDER_NW_OFF);
  339. if (pPkt[RTMP_SENDER_IDLEN_OFF] != 8)
  340. {
  341. AtalkLogBadPacket(pPortDesc,
  342. pSrcAddr,
  343. pDstAddr,
  344. pPkt,
  345. PktLen);
  346. break;
  347. }
  348. SenderNode.atn_Node = pPkt[RTMP_SENDER_ID_OFF];
  349. if (EXT_NET(pPortDesc))
  350. {
  351. GETSHORT2SHORT(&CableRange.anr_FirstNetwork, pPkt+RTMP_RANGE_START_OFF);
  352. GETSHORT2SHORT(&CableRange.anr_LastNetwork, pPkt+RTMP_RANGE_END_OFF);
  353. if (!AtalkCheckNetworkRange(&CableRange))
  354. break;
  355. }
  356. // On a non-extended network, we do not have to do any checking.
  357. // Just copy the information into A-ROUTER and THIS-NET
  358. if (!EXT_NET(pPortDesc))
  359. {
  360. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  361. pPortDesc->pd_Flags |= PD_SEEN_ROUTER_RECENTLY;
  362. KeSetEvent(&pPortDesc->pd_SeenRouterEvent, IO_NETWORK_INCREMENT, FALSE);
  363. pPortDesc->pd_LastRouterTime = AtalkGetCurrentTick();
  364. pPortDesc->pd_ARouter = SenderNode;
  365. if (pPortDesc->pd_NetworkRange.anr_FirstNetwork == UNKNOWN_NETWORK)
  366. {
  367. PATALK_NODE pNode;
  368. LONG i;
  369. pDdpAddr->ddpao_Node->an_NodeAddr.atn_Network =
  370. pPortDesc->pd_NetworkRange.anr_FirstNetwork =
  371. pPortDesc->pd_NetworkRange.anr_LastNetwork = SenderNode.atn_Network;
  372. pNode = pPortDesc->pd_Nodes;
  373. ASSERT (pNode != NULL);
  374. // Fixup all sockets to have the correct network numbers.
  375. ACQUIRE_SPIN_LOCK_DPC(&pNode->an_Lock);
  376. for (i = 0; i < NODE_DDPAO_HASH_SIZE; i ++)
  377. {
  378. PDDP_ADDROBJ pDdpAddr;
  379. for (pDdpAddr = pNode->an_DdpAoHash[i];
  380. pDdpAddr != NULL;
  381. pDdpAddr = pDdpAddr->ddpao_Next)
  382. {
  383. PREGD_NAME pRegdName;
  384. PPEND_NAME pPendName;
  385. ACQUIRE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  386. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  387. ("Setting socket %d to network %d\n",
  388. pDdpAddr->ddpao_Addr.ata_Socket, SenderNode.atn_Network));
  389. pDdpAddr->ddpao_Addr.ata_Network = SenderNode.atn_Network;
  390. // Now all regd/pend name tuples as well
  391. for (pRegdName = pDdpAddr->ddpao_RegNames;
  392. pRegdName != NULL;
  393. pRegdName = pRegdName->rdn_Next)
  394. {
  395. pRegdName->rdn_Tuple.tpl_Address.ata_Network = SenderNode.atn_Network;
  396. }
  397. for (pPendName = pDdpAddr->ddpao_PendNames;
  398. pPendName != NULL;
  399. pPendName = pPendName->pdn_Next)
  400. {
  401. ACQUIRE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  402. pPendName->pdn_pRegdName->rdn_Tuple.tpl_Address.ata_Network = SenderNode.atn_Network;
  403. RELEASE_SPIN_LOCK_DPC(&pPendName->pdn_Lock);
  404. }
  405. RELEASE_SPIN_LOCK_DPC(&pDdpAddr->ddpao_Lock);
  406. }
  407. }
  408. RELEASE_SPIN_LOCK_DPC(&pNode->an_Lock);
  409. }
  410. else if (pPortDesc->pd_NetworkRange.anr_FirstNetwork != SenderNode.atn_Network)
  411. {
  412. AtalkLogBadPacket(pPortDesc,
  413. pSrcAddr,
  414. pDstAddr,
  415. pPkt,
  416. PktLen);
  417. }
  418. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  419. break;
  420. }
  421. // On extended networks, we may want to reject the information: If we
  422. // already know about a router, the cable ranges must exacly match; If
  423. // we don't know about a router, our node's network number must be
  424. // within the cable range specified by the first tuple. The latter
  425. // test will discard the information if our node is in the startup
  426. // range (which is the right thing to do).
  427. if (pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  428. {
  429. if (!NW_RANGE_EQUAL(&CableRange, &pPortDesc->pd_NetworkRange))
  430. break;
  431. }
  432. // Okay, we've seen a valid Rtmp data, this should allow us to find the
  433. // zone name for the port. We do this outside of the
  434. // "PD_SEEN_ROUTER_RECENTLY" case because the first time a router
  435. // send out an Rtmp data it may not know everything yet, or
  436. // AtalkZipGetNetworkInfoForNode() may really do a
  437. // hard wait and we may need to try it a second time (due to not
  438. // repsonding to Aarp LocateNode's the first time through... the
  439. // second time our addresses should be cached by the remote router
  440. // and he won't need to do a LocateNode again).
  441. if (!(pPortDesc->pd_Flags & PD_VALID_DESIRED_ZONE))
  442. {
  443. if (!WITHIN_NETWORK_RANGE(pDdpAddr->ddpao_Addr.ata_Network,
  444. &CableRange))
  445. break;
  446. // MAKE THIS ASYNCHRONOUS CONDITIONALLY BASED ON THE CURRENT IRQL
  447. // A new router, see if it will tell us our zone name.
  448. if (KeGetCurrentIrql() == LOW_LEVEL)
  449. {
  450. QGNI Qgni;
  451. Qgni.qgni_pPortDesc = pPortDesc;
  452. Qgni.qgni_pDdpAddr = pDdpAddr;
  453. Qgni.qgni_SenderNode = SenderNode;
  454. Qgni.qgni_CableRange = CableRange;
  455. Qgni.qgni_FreeThis = FALSE;
  456. atalkRtmpGetNwInfo(&Qgni);
  457. }
  458. else
  459. {
  460. PQGNI pQgni;
  461. if ((pQgni = AtalkAllocMemory(sizeof(QGNI))) != NULL)
  462. {
  463. pQgni->qgni_pPortDesc = pPortDesc;
  464. pQgni->qgni_pDdpAddr = pDdpAddr;
  465. pQgni->qgni_SenderNode = SenderNode;
  466. pQgni->qgni_CableRange = CableRange;
  467. pQgni->qgni_FreeThis = TRUE;
  468. AtalkDdpReferenceByPtr(pDdpAddr, &Status);
  469. ASSERT (ATALK_SUCCESS(Status));
  470. ExInitializeWorkItem(&pQgni->qgni_WorkQItem,
  471. (PWORKER_THREAD_ROUTINE)atalkRtmpGetNwInfo,
  472. pQgni);
  473. ExQueueWorkItem(&pQgni->qgni_WorkQItem, CriticalWorkQueue);
  474. }
  475. }
  476. break;
  477. }
  478. // Update the fact that we heard from a router
  479. if ((pPortDesc->pd_Flags & PD_ROUTER_RUNNING) == 0)
  480. {
  481. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  482. pPortDesc->pd_Flags |= PD_SEEN_ROUTER_RECENTLY;
  483. KeSetEvent(&pPortDesc->pd_SeenRouterEvent, IO_NETWORK_INCREMENT, FALSE);
  484. pPortDesc->pd_LastRouterTime = AtalkGetCurrentTick();
  485. pPortDesc->pd_ARouter = SenderNode;
  486. pPortDesc->pd_NetworkRange = CableRange;
  487. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  488. }
  489. } while (FALSE);
  490. TimeE = KeQueryPerformanceCounter(NULL);
  491. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  492. INTERLOCKED_ADD_LARGE_INTGR_DPC(
  493. &pPortDesc->pd_PortStats.prtst_RtmpPacketInProcessTime,
  494. TimeD,
  495. &AtalkStatsLock.SpinLock);
  496. INTERLOCKED_INCREMENT_LONG_DPC(
  497. &pPortDesc->pd_PortStats.prtst_NumRtmpPacketsIn,
  498. &AtalkStatsLock.SpinLock);
  499. }
  500. VOID
  501. AtalkRtmpPacketInRouter(
  502. IN PPORT_DESCRIPTOR pPortDesc,
  503. IN PDDP_ADDROBJ pDdpAddr,
  504. IN PBYTE pPkt,
  505. IN USHORT PktLen,
  506. IN PATALK_ADDR pSrcAddr,
  507. IN PATALK_ADDR pDstAddr,
  508. IN ATALK_ERROR ErrorCode,
  509. IN BYTE DdpType,
  510. IN PVOID pHandlerCtx,
  511. IN BOOLEAN OptimizedPath,
  512. IN PVOID OptimizeCtx
  513. )
  514. {
  515. PBUFFER_DESC pBuffDesc = NULL;
  516. ATALK_NETWORKRANGE CableRange;
  517. ATALK_ERROR Status;
  518. TIME TimeS, TimeE, TimeD;
  519. PRTE pRte = NULL;
  520. BYTE RtmpCmd, NumHops;
  521. PBYTE Datagram;
  522. int i, index;
  523. USHORT RespSize;
  524. BOOLEAN RteLocked;
  525. SEND_COMPL_INFO SendInfo;
  526. TimeS = KeQueryPerformanceCounter(NULL);
  527. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  528. do
  529. {
  530. if (ErrorCode == ATALK_SOCKET_CLOSED)
  531. break;
  532. if (ErrorCode != ATALK_NO_ERROR)
  533. {
  534. break;
  535. }
  536. if (DdpType == DDPPROTO_RTMPREQUEST)
  537. {
  538. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  539. ("AtalkRtmpPacketInRouter: RtmpRequest\n"));
  540. if (PktLen < RTMP_REQ_DATAGRAM_SIZE)
  541. {
  542. AtalkLogBadPacket(pPortDesc,
  543. pSrcAddr,
  544. pDstAddr,
  545. pPkt,
  546. PktLen);
  547. break;
  548. }
  549. RtmpCmd = pPkt[RTMP_REQ_CMD_OFF];
  550. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  551. ("AtalkRtmpPacketInRouter: RtmpRequest %d\n", RtmpCmd));
  552. if ((RtmpCmd == RTMP_DATA_REQUEST) ||
  553. (RtmpCmd == RTMP_ENTIRE_DATA_REQUEST))
  554. {
  555. atalkRtmpSendRoutingData(pPortDesc, pSrcAddr,
  556. (BOOLEAN)(RtmpCmd == RTMP_DATA_REQUEST));
  557. break;
  558. }
  559. else if (RtmpCmd != RTMP_REQUEST)
  560. {
  561. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  562. ("atalkRtmpPacketInRouter: RtmpCmd %d\n", RtmpCmd));
  563. AtalkLogBadPacket(pPortDesc,
  564. pSrcAddr,
  565. pDstAddr,
  566. pPkt,
  567. PktLen);
  568. break;
  569. }
  570. // This is a standard Rtmp Request. Do the needfull
  571. // Send an Rtmp response to this guy. Start off by allocating
  572. // a buffer descriptor
  573. pBuffDesc = AtalkAllocBuffDesc(NULL,
  574. RTMP_RESPONSE_MAX_SIZE,
  575. BD_CHAR_BUFFER | BD_FREE_BUFFER);
  576. if (pBuffDesc == NULL)
  577. {
  578. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  579. ("AtalkRtmpPacketInRouter: AtalkAllocBuffDesc failed\n"));
  580. break;
  581. }
  582. Datagram = pBuffDesc->bd_CharBuffer;
  583. PUTSHORT2SHORT(Datagram + RTMP_SENDER_NW_OFF,
  584. pPortDesc->pd_ARouter.atn_Network);
  585. Datagram[RTMP_SENDER_IDLEN_OFF] = 8;
  586. Datagram[RTMP_SENDER_ID_OFF] = pPortDesc->pd_ARouter.atn_Node;
  587. // On extended port, we also want to add the initial network
  588. // range tuple
  589. RespSize = RTMP_SENDER_ID_OFF + sizeof(BYTE);
  590. if (EXT_NET(pPortDesc))
  591. {
  592. PUTSHORT2SHORT(Datagram+RTMP_RANGE_START_OFF,
  593. pPortDesc->pd_NetworkRange.anr_FirstNetwork);
  594. PUTSHORT2SHORT(Datagram+RTMP_RANGE_END_OFF,
  595. pPortDesc->pd_NetworkRange.anr_LastNetwork);
  596. Datagram[RTMP_TUPLE_TYPE_OFF] = RTMP_TUPLE_WITHRANGE;
  597. RespSize = RTMP_RANGE_END_OFF + sizeof(USHORT);
  598. }
  599. // Set the length in the buffer descriptor.
  600. AtalkSetSizeOfBuffDescData(pBuffDesc, RespSize);
  601. // Send the response
  602. ASSERT(pBuffDesc->bd_Length > 0);
  603. SendInfo.sc_TransmitCompletion = atalkRtmpSendComplete;
  604. SendInfo.sc_Ctx1 = pBuffDesc;
  605. // SendInfo.sc_Ctx2 = NULL;
  606. // SendInfo.sc_Ctx3 = NULL;
  607. if (!ATALK_SUCCESS(Status = AtalkDdpSend(pDdpAddr,
  608. pSrcAddr,
  609. (BYTE)DDPPROTO_RTMPRESPONSEORDATA,
  610. FALSE,
  611. pBuffDesc,
  612. NULL,
  613. 0,
  614. NULL,
  615. &SendInfo)))
  616. {
  617. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  618. ("AtalkRtmpPacketInRouter: DdpSend failed %ld\n", ErrorCode));
  619. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  620. ("AtalkRtmpPacketInRouter: AtalkDdpSend Failed %ld\n", Status));
  621. AtalkFreeBuffDesc(pBuffDesc);
  622. }
  623. pBuffDesc = NULL;
  624. break;
  625. }
  626. else if (DdpType != DDPPROTO_RTMPRESPONSEORDATA)
  627. {
  628. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  629. ("AtalkRtmpPacketInRouter: Not ours !!!\n"));
  630. break;
  631. }
  632. ASSERT (DdpType == DDPPROTO_RTMPRESPONSEORDATA);
  633. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  634. ("AtalkRtmpPacketInRouter: RtmpResponse\n"));
  635. if ((PktLen < (RTMP_SENDER_IDLEN_OFF + 1)) ||
  636. (pPkt[RTMP_SENDER_IDLEN_OFF] != 8))
  637. {
  638. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  639. ("AtalkRtmpPacketInRouter: %sExt net, PktLen %d, SenderId %d\n",
  640. EXT_NET(pPortDesc) ? "" : "Non", PktLen, pPkt[RTMP_SENDER_IDLEN_OFF]));
  641. AtalkLogBadPacket(pPortDesc,
  642. pSrcAddr,
  643. pDstAddr,
  644. pPkt,
  645. PktLen);
  646. break;
  647. }
  648. // For non-extended networks, we should have a leading version stamp
  649. if (EXT_NET(pPortDesc))
  650. {
  651. // Source could be bad (coming in from a half port) so in this
  652. // case use the source from the rtmp packet
  653. if (pSrcAddr->ata_Network == UNKNOWN_NETWORK)
  654. {
  655. if (PktLen < RTMP_SENDER_ID_OFF + 1)
  656. {
  657. ASSERT(0);
  658. break;
  659. }
  660. GETSHORT2SHORT(&pSrcAddr->ata_Network, pPkt+RTMP_SENDER_NW_OFF);
  661. pSrcAddr->ata_Node = pPkt[RTMP_SENDER_ID_OFF];
  662. }
  663. index = RTMP_SENDER_ID_OFF + 1;
  664. }
  665. else
  666. {
  667. USHORT SenderId;
  668. if (PktLen < RTMP_TUPLE_TYPE_OFF+1)
  669. {
  670. ASSERT(0);
  671. break;
  672. }
  673. GETSHORT2SHORT(&SenderId, pPkt + RTMP_SENDER_ID_OFF + 1);
  674. if ((SenderId != 0) ||
  675. (pPkt[RTMP_TUPLE_TYPE_OFF] != RTMP_VERSION))
  676. {
  677. AtalkLogBadPacket(pPortDesc,
  678. pSrcAddr,
  679. pDstAddr,
  680. pPkt,
  681. PktLen);
  682. break;
  683. }
  684. index = RTMP_SENDER_ID_OFF + 4;
  685. }
  686. // Walk though the routing tuples. Ensure we atleast have a
  687. // non-extended tuple
  688. RteLocked = FALSE;
  689. while ((index + sizeof(USHORT) + sizeof(BYTE)) <= PktLen)
  690. {
  691. BOOLEAN FoundOverlap;
  692. // Dereference the previous RTE, if any
  693. if (pRte != NULL)
  694. {
  695. if (RteLocked)
  696. {
  697. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  698. RteLocked = FALSE;
  699. }
  700. AtalkRtmpDereferenceRte(pRte, FALSE);
  701. pRte = NULL;
  702. }
  703. GETSHORT2SHORT(&CableRange.anr_FirstNetwork, pPkt+index);
  704. index += sizeof(USHORT);
  705. NumHops = pPkt[index++];
  706. CableRange.anr_LastNetwork = CableRange.anr_FirstNetwork;
  707. if (NumHops & RTMP_EXT_TUPLE_MASK)
  708. {
  709. if ((index + sizeof(USHORT) + sizeof(BYTE)) > PktLen)
  710. {
  711. ASSERT(0);
  712. AtalkLogBadPacket(pPortDesc,
  713. pSrcAddr,
  714. pDstAddr,
  715. pPkt,
  716. PktLen);
  717. break;
  718. }
  719. GETSHORT2SHORT(&CableRange.anr_LastNetwork, pPkt+index);
  720. index += sizeof(USHORT);
  721. if (pPkt[index++] != RTMP_VERSION)
  722. {
  723. AtalkLogBadPacket(pPortDesc,
  724. pSrcAddr,
  725. pDstAddr,
  726. pPkt,
  727. PktLen);
  728. break;
  729. }
  730. }
  731. NumHops &= RTMP_NUM_HOPS_MASK;
  732. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  733. ("AtalkRtmpPacketInRouter: Response - Port %Z, Hops %d, CableRange %d,%d\n",
  734. &pPortDesc->pd_AdapterKey, NumHops,
  735. CableRange.anr_FirstNetwork, CableRange.anr_LastNetwork));
  736. if (!AtalkCheckNetworkRange(&CableRange))
  737. continue;
  738. // Check if this tuple concerns a network range that we
  739. // already know about
  740. pRte = AtalkRtmpReferenceRte(CableRange.anr_FirstNetwork);
  741. if ((pRte != NULL) &&
  742. NW_RANGE_EQUAL(&pRte->rte_NwRange, &CableRange))
  743. {
  744. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  745. RteLocked = TRUE;
  746. // Check for "notify neighbor" telling us that an entry is bad
  747. if ((NumHops == RTMP_NUM_HOPS_MASK) &&
  748. (pRte->rte_NextRouter.atn_Network == pSrcAddr->ata_Network) &&
  749. (pRte->rte_NextRouter.atn_Node == pSrcAddr->ata_Node))
  750. {
  751. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  752. ("AtalkRtmpPacketInRouter: Notify Neighbor State %d\n",
  753. pRte->rte_State));
  754. if (pRte->rte_State != UGLY)
  755. pRte->rte_State = BAD;
  756. continue;
  757. }
  758. // If we are hearing about one of our directly connected
  759. // nets, we know best. Ignore the information.
  760. if (pRte->rte_NumHops == 0)
  761. {
  762. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  763. ("AtalkRtmpPacketInRouter: Ignoring - hop count 0\n",
  764. pRte->rte_State));
  765. continue;
  766. }
  767. // Check for previously bad entry, and a short enough
  768. // path with this tuple. Also if it shorter or equi-
  769. // distant path to target network. If so, replace the entry
  770. if ((NumHops < RTMP_MAX_HOPS) &&
  771. ((pRte->rte_NumHops >= (NumHops + 1)) ||
  772. (pRte->rte_State >= BAD)))
  773. {
  774. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_WARN,
  775. ("AtalkRtmpPacketInRouter: Updating Rte from:\n\tRange %d,%d Hops %d Port %Z NextRouter %d.%d\n",
  776. pRte->rte_NwRange.anr_FirstNetwork,
  777. pRte->rte_NwRange.anr_LastNetwork,
  778. pRte->rte_NumHops,
  779. &pRte->rte_PortDesc->pd_AdapterKey,
  780. pRte->rte_NextRouter.atn_Node,
  781. pRte->rte_NextRouter.atn_Network));
  782. pRte->rte_NumHops = NumHops + 1;
  783. pRte->rte_NextRouter.atn_Network = pSrcAddr->ata_Network;
  784. pRte->rte_NextRouter.atn_Node = pSrcAddr->ata_Node;
  785. if (pRte->rte_PortDesc != pPortDesc)
  786. {
  787. ATALK_ERROR Error;
  788. AtalkPortDereference(pRte->rte_PortDesc);
  789. AtalkPortReferenceByPtrDpc(pPortDesc, &Error);
  790. ASSERT (ATALK_SUCCESS(Error));
  791. pRte->rte_PortDesc = pPortDesc;
  792. }
  793. pRte->rte_State = GOOD;
  794. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_WARN,
  795. ("to:\tRange %d,%d Hops %d NextRouter %d.%d\n",
  796. pRte->rte_NwRange.anr_FirstNetwork,
  797. pRte->rte_NwRange.anr_LastNetwork,
  798. pRte->rte_NumHops,
  799. pRte->rte_NextRouter.atn_Node,
  800. pRte->rte_NextRouter.atn_Network));
  801. continue;
  802. }
  803. // Check for the same router still thinking it has a path
  804. // to the network, but it is further away now. If so
  805. // update the entry
  806. if ((pRte->rte_PortDesc == pPortDesc) &&
  807. (pRte->rte_NextRouter.atn_Network == pSrcAddr->ata_Network) &&
  808. (pRte->rte_NextRouter.atn_Node == pSrcAddr->ata_Node))
  809. {
  810. pRte->rte_NumHops = NumHops + 1;
  811. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  812. ("AtalkRtmpPacketInRouter: NumHops for Rte %lx changed to %d\n",
  813. pRte, pRte->rte_NumHops));
  814. if (pRte->rte_NumHops < 16)
  815. pRte->rte_State = GOOD;
  816. else
  817. {
  818. // atalkRtmpRemoveRte(pRte);
  819. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  820. ("AtalkRtmpPacketInRouter: Removing Rte\n"));
  821. pRte->rte_Flags |= RTE_DELETE;
  822. pRte->rte_RefCount --;
  823. }
  824. }
  825. continue;
  826. }
  827. // Dereference any previous RTEs
  828. if (pRte != NULL)
  829. {
  830. if (RteLocked)
  831. {
  832. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  833. RteLocked = FALSE;
  834. }
  835. AtalkRtmpDereferenceRte(pRte, FALSE);
  836. pRte = NULL;
  837. }
  838. // Walk thru the entire routing table making sure the current
  839. // tuple does not overlap with anything we already have (since
  840. // it did not match. If we find an overlap, ignore the tuple
  841. // (a network configuration error, no doubt), else add it as
  842. // a new network range !!
  843. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock);
  844. FoundOverlap = FALSE;
  845. for (i = 0; !FoundOverlap && (i < NUM_RTMP_HASH_BUCKETS); i++)
  846. {
  847. for (pRte = AtalkRoutingTable[i];
  848. pRte != NULL; pRte = pRte->rte_Next)
  849. {
  850. if (AtalkRangesOverlap(&pRte->rte_NwRange, &CableRange))
  851. {
  852. FoundOverlap = TRUE;
  853. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_WARN,
  854. ("AtalkRtmpPacketInRouter: Overlapped ranges %d,%d & %d,%d\n",
  855. pRte->rte_NwRange.anr_FirstNetwork,
  856. pRte->rte_NwRange.anr_LastNetwork,
  857. CableRange.anr_FirstNetwork,
  858. CableRange.anr_LastNetwork));
  859. break;
  860. }
  861. }
  862. }
  863. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  864. pRte = NULL; // We do not want to Dereference this !!!
  865. if (FoundOverlap)
  866. {
  867. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  868. ("AtalkRtmpPacketInRouter: Found overlapped ranges\n"));
  869. continue;
  870. }
  871. // Enter this new network range
  872. if (NumHops < RTMP_MAX_HOPS)
  873. {
  874. ATALK_NODEADDR NextRouter;
  875. NextRouter.atn_Network = pSrcAddr->ata_Network;
  876. NextRouter.atn_Node = pSrcAddr->ata_Node;
  877. atalkRtmpCreateRte(CableRange,
  878. pPortDesc,
  879. &NextRouter,
  880. NumHops + 1);
  881. }
  882. }
  883. } while (FALSE);
  884. if (pRte != NULL)
  885. {
  886. if (RteLocked)
  887. {
  888. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  889. // RteLocked = FALSE;
  890. }
  891. AtalkRtmpDereferenceRte(pRte, FALSE);
  892. // pRte = NULL;
  893. }
  894. if (pBuffDesc != NULL)
  895. AtalkFreeBuffDesc(pBuffDesc);
  896. TimeE = KeQueryPerformanceCounter(NULL);
  897. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  898. INTERLOCKED_ADD_LARGE_INTGR_DPC(
  899. &pPortDesc->pd_PortStats.prtst_RtmpPacketInProcessTime,
  900. TimeD,
  901. &AtalkStatsLock.SpinLock);
  902. INTERLOCKED_INCREMENT_LONG_DPC(
  903. &pPortDesc->pd_PortStats.prtst_NumRtmpPacketsIn,
  904. &AtalkStatsLock.SpinLock);
  905. }
  906. /*** AtalkReferenceRte
  907. *
  908. */
  909. PRTE
  910. AtalkRtmpReferenceRte(
  911. IN USHORT Network
  912. )
  913. {
  914. int i, index, rindex;
  915. PRTE pRte;
  916. KIRQL OldIrql;
  917. index = (int)((Network >> 4) % NUM_RTMP_HASH_BUCKETS);
  918. rindex = (int)((Network >> 6) % NUM_RECENT_ROUTES);
  919. // First try the recent route cache
  920. ACQUIRE_SPIN_LOCK(&AtalkRteLock, &OldIrql);
  921. if (((pRte = AtalkRecentRoutes[rindex]) == NULL) ||
  922. !IN_NETWORK_RANGE(Network, pRte))
  923. {
  924. // We did not find it in the recent routes cache,
  925. // check in the real table
  926. for (pRte = AtalkRoutingTable[index];
  927. pRte != NULL;
  928. pRte = pRte->rte_Next)
  929. {
  930. if (IN_NETWORK_RANGE(Network, pRte))
  931. break;
  932. }
  933. // If we did not find here. Check all routing tables.
  934. // If we do, cache the info
  935. if (pRte == NULL)
  936. {
  937. for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i++)
  938. {
  939. for (pRte = AtalkRoutingTable[i];
  940. pRte != NULL;
  941. pRte = pRte->rte_Next)
  942. {
  943. if (IN_NETWORK_RANGE(Network, pRte))
  944. {
  945. AtalkRecentRoutes[rindex] = pRte;
  946. break;
  947. }
  948. }
  949. // if we found an entry, search no further.
  950. if (pRte != NULL)
  951. break;
  952. }
  953. }
  954. }
  955. if (pRte != NULL)
  956. {
  957. ASSERT(VALID_RTE(pRte));
  958. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  959. pRte->rte_RefCount ++;
  960. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  961. ("AtalkRtmpReferenceRte: Rte %lx, PostCount %d\n",
  962. pRte, pRte->rte_RefCount));
  963. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  964. }
  965. RELEASE_SPIN_LOCK(&AtalkRteLock, OldIrql);
  966. return (pRte);
  967. }
  968. /*** AtalkRtmpDereferenceRte
  969. *
  970. */
  971. VOID
  972. AtalkRtmpDereferenceRte(
  973. IN PRTE pRte,
  974. IN BOOLEAN LockHeld
  975. )
  976. {
  977. PRTE * ppRte;
  978. int Index;
  979. BOOLEAN KillCache = FALSE, Kill = FALSE;
  980. KIRQL OldIrql;
  981. PPORT_DESCRIPTOR pPortDesc;
  982. ASSERT(VALID_RTE(pRte));
  983. ASSERT(pRte->rte_RefCount > 0);
  984. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  985. ("AtalkRtmpDereferenceRte: Rte %lx, PreCount %d\n",
  986. pRte, pRte->rte_RefCount));
  987. ACQUIRE_SPIN_LOCK(&pRte->rte_Lock, &OldIrql);
  988. pRte->rte_RefCount --;
  989. KillCache = (pRte->rte_Flags & RTE_DELETE) ? TRUE : FALSE;
  990. if (pRte->rte_RefCount == 0)
  991. {
  992. ASSERT (pRte->rte_Flags & RTE_DELETE);
  993. KillCache = Kill = TRUE;
  994. }
  995. RELEASE_SPIN_LOCK(&pRte->rte_Lock, OldIrql);
  996. if (KillCache)
  997. {
  998. pPortDesc = pRte->rte_PortDesc;
  999. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_WARN,
  1000. ("atalkRtmpDereferenceRte: Removing from cache for port %Z, Range %d, %d\n",
  1001. &pRte->rte_PortDesc->pd_AdapterKey,
  1002. pRte->rte_NwRange.anr_FirstNetwork,
  1003. pRte->rte_NwRange.anr_LastNetwork));
  1004. if (!LockHeld)
  1005. ACQUIRE_SPIN_LOCK(&AtalkRteLock, &OldIrql);
  1006. // Walk through the recent routes cache and kill All found
  1007. for (Index = 0; Index < NUM_RECENT_ROUTES; Index ++)
  1008. {
  1009. if (AtalkRecentRoutes[Index] == pRte)
  1010. {
  1011. AtalkRecentRoutes[Index] = NULL;
  1012. }
  1013. }
  1014. if (Kill)
  1015. {
  1016. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_WARN,
  1017. ("atalkRtmpDereferenceRte: Removing for port %Z, Range %d, %d\n",
  1018. &pRte->rte_PortDesc->pd_AdapterKey,
  1019. pRte->rte_NwRange.anr_FirstNetwork,
  1020. pRte->rte_NwRange.anr_LastNetwork));
  1021. Index = (pRte->rte_NwRange.anr_FirstNetwork >> 4) % NUM_RTMP_HASH_BUCKETS;
  1022. for (ppRte = &AtalkRoutingTable[Index];
  1023. *ppRte != NULL;
  1024. ppRte = &(*ppRte)->rte_Next)
  1025. {
  1026. if (pRte == *ppRte)
  1027. {
  1028. *ppRte = pRte->rte_Next;
  1029. AtalkZoneFreeList(pRte->rte_ZoneList);
  1030. AtalkFreeMemory(pRte);
  1031. break;
  1032. }
  1033. }
  1034. AtalkPortDereference(pPortDesc);
  1035. }
  1036. if (!LockHeld)
  1037. RELEASE_SPIN_LOCK(&AtalkRteLock, OldIrql);
  1038. }
  1039. }
  1040. /*** atalkCreateRte
  1041. *
  1042. */
  1043. BOOLEAN
  1044. atalkRtmpCreateRte(
  1045. IN ATALK_NETWORKRANGE NwRange,
  1046. IN PPORT_DESCRIPTOR pPortDesc,
  1047. IN PATALK_NODEADDR pNextRouter,
  1048. IN int NumHops
  1049. )
  1050. {
  1051. ATALK_ERROR Error;
  1052. PRTE pRte;
  1053. int index, rindex;
  1054. KIRQL OldIrql;
  1055. BOOLEAN Success = FALSE;
  1056. index = (int)((NwRange.anr_FirstNetwork >> 4) % NUM_RTMP_HASH_BUCKETS);
  1057. rindex = (int)((NwRange.anr_FirstNetwork >> 6) % NUM_RECENT_ROUTES);
  1058. // First reference the port
  1059. AtalkPortReferenceByPtr(pPortDesc, &Error);
  1060. if (ATALK_SUCCESS(Error))
  1061. {
  1062. if ((pRte = AtalkAllocMemory(sizeof(RTE))) != NULL)
  1063. {
  1064. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  1065. ("atalkRtmpCreateRte: Creating for port %Z, Range %d,%d Hops %d index %d\n",
  1066. &pPortDesc->pd_AdapterKey,
  1067. NwRange.anr_FirstNetwork,
  1068. NwRange.anr_LastNetwork,
  1069. NumHops,
  1070. index));
  1071. #if DBG
  1072. pRte->rte_Signature = RTE_SIGNATURE;
  1073. #endif
  1074. INITIALIZE_SPIN_LOCK(&pRte->rte_Lock);
  1075. pRte->rte_RefCount = 1; // Creation Reference
  1076. pRte->rte_State = GOOD;
  1077. pRte->rte_Flags = 0;
  1078. pRte->rte_NwRange = NwRange;
  1079. pRte->rte_NumHops = (BYTE)NumHops;
  1080. pRte->rte_PortDesc = pPortDesc;
  1081. pRte->rte_NextRouter = *pNextRouter;
  1082. pRte->rte_ZoneList = NULL;
  1083. // Link this in the global table
  1084. ACQUIRE_SPIN_LOCK(&AtalkRteLock, &OldIrql);
  1085. pRte->rte_Next = AtalkRoutingTable[index];
  1086. AtalkRoutingTable[index] = pRte;
  1087. AtalkRecentRoutes[rindex] = pRte;
  1088. RELEASE_SPIN_LOCK(&AtalkRteLock, OldIrql);
  1089. Success = TRUE;
  1090. }
  1091. else
  1092. {
  1093. AtalkPortDereference(pPortDesc);
  1094. }
  1095. }
  1096. return Success;
  1097. }
  1098. /*** atalkRtmpRemoveRte
  1099. *
  1100. */
  1101. BOOLEAN
  1102. atalkRtmpRemoveRte(
  1103. IN USHORT Network
  1104. )
  1105. {
  1106. PRTE pRte;
  1107. KIRQL OldIrql;
  1108. if ((pRte = AtalkRtmpReferenceRte(Network)) != NULL)
  1109. {
  1110. ACQUIRE_SPIN_LOCK(&pRte->rte_Lock, &OldIrql);
  1111. pRte->rte_RefCount --; // Take away creation reference
  1112. pRte->rte_Flags |= RTE_DELETE;
  1113. RELEASE_SPIN_LOCK(&pRte->rte_Lock, OldIrql);
  1114. AtalkRtmpDereferenceRte(pRte, FALSE);
  1115. }
  1116. return (pRte != NULL);
  1117. }
  1118. /*** AtalkRtmpKillPortRtes
  1119. *
  1120. */
  1121. VOID FASTCALL
  1122. AtalkRtmpKillPortRtes(
  1123. IN PPORT_DESCRIPTOR pPortDesc
  1124. )
  1125. {
  1126. // At this point, we are unloading and there are no race conditions
  1127. // or lock contentions. Do not bother locking down the rtmp tables
  1128. if (AtalkRoutingTable != NULL)
  1129. {
  1130. int i;
  1131. PRTE pRte, pTmp;
  1132. KIRQL OldIrql;
  1133. ACQUIRE_SPIN_LOCK(&AtalkRteLock, &OldIrql);
  1134. for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i++)
  1135. {
  1136. for (pRte = AtalkRoutingTable[i];
  1137. pRte != NULL;
  1138. pRte = pTmp)
  1139. {
  1140. pTmp = pRte->rte_Next;
  1141. if (pRte->rte_PortDesc == pPortDesc)
  1142. {
  1143. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1144. pRte->rte_Flags |= RTE_DELETE;
  1145. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1146. AtalkRtmpDereferenceRte(pRte, TRUE);
  1147. }
  1148. }
  1149. }
  1150. RELEASE_SPIN_LOCK(&AtalkRteLock, OldIrql);
  1151. }
  1152. }
  1153. /*** AtalkRtmpAgingTimer
  1154. *
  1155. */
  1156. LONG FASTCALL
  1157. AtalkRtmpAgingTimer(
  1158. IN PTIMERLIST pContext,
  1159. IN BOOLEAN TimerShuttingDown
  1160. )
  1161. {
  1162. PPORT_DESCRIPTOR pPortDesc;
  1163. ATALK_ERROR error;
  1164. LONG Now;
  1165. pPortDesc = CONTAINING_RECORD(pContext, PORT_DESCRIPTOR, pd_RtmpAgingTimer);
  1166. if (TimerShuttingDown ||
  1167. (pPortDesc->pd_Flags & PD_CLOSING))
  1168. {
  1169. AtalkPortDereferenceDpc(pPortDesc);
  1170. return ATALK_TIMER_NO_REQUEUE;
  1171. }
  1172. Now = AtalkGetCurrentTick();
  1173. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1174. if (((pPortDesc->pd_Flags &
  1175. (PD_ACTIVE | PD_ROUTER_RUNNING | PD_SEEN_ROUTER_RECENTLY)) ==
  1176. (PD_ACTIVE | PD_SEEN_ROUTER_RECENTLY)) &&
  1177. ((pPortDesc->pd_LastRouterTime + RTMP_AGING_TIMER) < Now))
  1178. {
  1179. // Age out A-ROUTER. On extended networks age out THIS-CABLE-RANGE
  1180. // and THIS-ZONE too
  1181. KeClearEvent(&pPortDesc->pd_SeenRouterEvent);
  1182. pPortDesc->pd_Flags &= ~PD_SEEN_ROUTER_RECENTLY;
  1183. if (EXT_NET(pPortDesc))
  1184. {
  1185. pPortDesc->pd_Flags &= ~PD_VALID_DESIRED_ZONE;
  1186. pPortDesc->pd_NetworkRange.anr_FirstNetwork = FIRST_VALID_NETWORK;
  1187. pPortDesc->pd_NetworkRange.anr_LastNetwork = LAST_STARTUP_NETWORK;
  1188. // If we have a zone multicast address that is not broadcast, age it out
  1189. if (!AtalkFixedCompareCaseSensitive(pPortDesc->pd_ZoneMulticastAddr,
  1190. MAX_HW_ADDR_LEN,
  1191. pPortDesc->pd_BroadcastAddr,
  1192. MAX_HW_ADDR_LEN))
  1193. {
  1194. // Release lock before calling in to remove multicast address
  1195. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1196. (*pPortDesc->pd_RemoveMulticastAddr)(pPortDesc,
  1197. pPortDesc->pd_ZoneMulticastAddr,
  1198. FALSE,
  1199. NULL,
  1200. NULL);
  1201. // Re-acquire the lock now
  1202. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1203. }
  1204. RtlZeroMemory(pPortDesc->pd_ZoneMulticastAddr, MAX_HW_ADDR_LEN);
  1205. }
  1206. }
  1207. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  1208. return ATALK_TIMER_REQUEUE;
  1209. }
  1210. /*** atalkRtmpSendTimer
  1211. *
  1212. */
  1213. LOCAL LONG FASTCALL
  1214. atalkRtmpSendTimer(
  1215. IN PTIMERLIST pContext,
  1216. IN BOOLEAN TimerShuttingDown
  1217. )
  1218. {
  1219. PPORT_DESCRIPTOR pPortDesc;
  1220. ATALK_ADDR Destination;
  1221. ATALK_ERROR error;
  1222. pPortDesc = CONTAINING_RECORD(pContext, PORT_DESCRIPTOR, pd_RtmpSendTimer);
  1223. if (TimerShuttingDown ||
  1224. (pPortDesc->pd_Flags & PD_CLOSING))
  1225. {
  1226. AtalkPortDereferenceDpc(pPortDesc);
  1227. return ATALK_TIMER_NO_REQUEUE;
  1228. }
  1229. Destination.ata_Network = CABLEWIDE_BROADCAST_NETWORK;
  1230. Destination.ata_Node = ATALK_BROADCAST_NODE;
  1231. Destination.ata_Socket = RTMP_SOCKET;
  1232. if (((pPortDesc->pd_Flags &
  1233. (PD_ACTIVE | PD_ROUTER_RUNNING)) == (PD_ACTIVE | PD_ROUTER_RUNNING)))
  1234. {
  1235. atalkRtmpSendRoutingData(pPortDesc, &Destination, TRUE);
  1236. }
  1237. return ATALK_TIMER_REQUEUE;
  1238. }
  1239. /*** atalkValidityTimer
  1240. *
  1241. */
  1242. LOCAL LONG FASTCALL
  1243. atalkRtmpValidityTimer(
  1244. IN PTIMERLIST pContext,
  1245. IN BOOLEAN TimerShuttingDown
  1246. )
  1247. {
  1248. PRTE pRte, pNext;
  1249. int i;
  1250. if (TimerShuttingDown)
  1251. return ATALK_TIMER_NO_REQUEUE;
  1252. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock);
  1253. for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i++)
  1254. {
  1255. for (pRte = AtalkRoutingTable[i]; pRte != NULL; pRte = pNext)
  1256. {
  1257. BOOLEAN Deref;
  1258. pNext = pRte->rte_Next;
  1259. if (pRte->rte_NumHops == 0)
  1260. continue;
  1261. Deref = FALSE;
  1262. ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1263. switch (pRte->rte_State)
  1264. {
  1265. case GOOD:
  1266. case SUSPECT:
  1267. case BAD:
  1268. pRte->rte_State++;
  1269. break;
  1270. case UGLY:
  1271. Deref = TRUE;
  1272. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_WARN,
  1273. ("atalkRtmpValidityTimer: Killing pRte %lx\n"));
  1274. pRte->rte_Flags |= RTE_DELETE;
  1275. break;
  1276. default:
  1277. // How did we get here ?
  1278. ASSERT(0);
  1279. KeBugCheck(0);
  1280. }
  1281. RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock);
  1282. if (Deref)
  1283. AtalkRtmpDereferenceRte(pRte, TRUE);
  1284. }
  1285. }
  1286. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  1287. return ATALK_TIMER_REQUEUE;
  1288. }
  1289. /*** atalkRtmpSendRoutingData
  1290. *
  1291. */
  1292. LOCAL VOID
  1293. atalkRtmpSendRoutingData(
  1294. IN PPORT_DESCRIPTOR pPortDesc,
  1295. IN PATALK_ADDR pDstAddr,
  1296. IN BOOLEAN fSplitHorizon
  1297. )
  1298. {
  1299. int i, index;
  1300. PRTE pRte;
  1301. PBYTE Datagram;
  1302. PDDP_ADDROBJ pDdpAddr;
  1303. ATALK_ADDR SrcAddr;
  1304. PBUFFER_DESC pBuffDesc,
  1305. pBuffDescStart = NULL,
  1306. *ppBuffDesc = &pBuffDescStart;
  1307. SEND_COMPL_INFO SendInfo;
  1308. ATALK_ERROR Status;
  1309. BOOLEAN AllocNewBuffDesc = TRUE;
  1310. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  1311. // Compute the source socket: Rtmp socket on our routers node
  1312. SrcAddr.ata_Network = pPortDesc->pd_ARouter.atn_Network;
  1313. SrcAddr.ata_Node = pPortDesc->pd_ARouter.atn_Node;
  1314. SrcAddr.ata_Socket = RTMP_SOCKET;
  1315. AtalkDdpReferenceByAddr(pPortDesc, &SrcAddr, &pDdpAddr, &Status);
  1316. if (!ATALK_SUCCESS(Status))
  1317. {
  1318. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  1319. ("atalkRtmpSendRoutingData: AtalkDdpRefByAddr failed %ld for %d.%d\n",
  1320. Status, SrcAddr.ata_Network, SrcAddr.ata_Node));
  1321. return;
  1322. }
  1323. // Walk through the rtmp table building a tuple for each network.
  1324. // Note: We may have to send multiple-packets. Each packet needs
  1325. // to be allocated afresh. The completion routine will free
  1326. // it up.
  1327. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock);
  1328. for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i++)
  1329. {
  1330. for (pRte = AtalkRoutingTable[i];
  1331. pRte != NULL;
  1332. pRte = pRte->rte_Next)
  1333. {
  1334. if (AllocNewBuffDesc)
  1335. {
  1336. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  1337. MAX_DGRAM_SIZE,
  1338. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  1339. break;
  1340. Datagram = pBuffDesc->bd_CharBuffer;
  1341. *ppBuffDesc = pBuffDesc;
  1342. pBuffDesc->bd_Next = NULL;
  1343. ppBuffDesc = &pBuffDesc->bd_Next;
  1344. AllocNewBuffDesc = FALSE;
  1345. // Build the static part of the rtmp data packet
  1346. PUTSHORT2SHORT(Datagram+RTMP_SENDER_NW_OFF,
  1347. pPortDesc->pd_ARouter.atn_Network);
  1348. Datagram[RTMP_SENDER_IDLEN_OFF] = 8;
  1349. Datagram[RTMP_SENDER_ID_OFF] = pPortDesc->pd_ARouter.atn_Node;
  1350. // For non-extended network, we also need the version stamp.
  1351. // For extended network, include a initial network range tuple
  1352. // as part of the header
  1353. if (EXT_NET(pPortDesc))
  1354. {
  1355. PUTSHORT2SHORT(Datagram + RTMP_RANGE_START_OFF,
  1356. pPortDesc->pd_NetworkRange.anr_FirstNetwork);
  1357. PUTSHORT2SHORT(Datagram + RTMP_RANGE_END_OFF,
  1358. pPortDesc->pd_NetworkRange.anr_LastNetwork);
  1359. Datagram[RTMP_TUPLE_TYPE_OFF] = RTMP_TUPLE_WITHRANGE;
  1360. Datagram[RTMP_VERSION_OFF_EXT] = RTMP_VERSION;
  1361. index = RTMP_VERSION_OFF_EXT + 1; // Beyond version
  1362. }
  1363. else
  1364. {
  1365. PUTSHORT2SHORT(Datagram + RTMP_SENDER_ID_OFF + 1, 0);
  1366. Datagram[RTMP_VERSION_OFF_NE] = RTMP_VERSION;
  1367. index = RTMP_VERSION_OFF_NE + 1; // Beyond version
  1368. }
  1369. }
  1370. // See if we should skip the current tuple due to split horizon
  1371. if (fSplitHorizon && (pRte->rte_NumHops != 0) &&
  1372. (pPortDesc == pRte->rte_PortDesc))
  1373. continue;
  1374. // Skip the ports range since we already copied it as the
  1375. // first tuple, but only if extended port
  1376. if (EXT_NET(pPortDesc) &&
  1377. (pPortDesc->pd_NetworkRange.anr_FirstNetwork ==
  1378. pRte->rte_NwRange.anr_FirstNetwork) &&
  1379. (pPortDesc->pd_NetworkRange.anr_FirstNetwork ==
  1380. pRte->rte_NwRange.anr_FirstNetwork))
  1381. continue;
  1382. // Place the tuple in the packet
  1383. PUTSHORT2SHORT(Datagram+index, pRte->rte_NwRange.anr_FirstNetwork);
  1384. index += sizeof(SHORT);
  1385. // Do 'notify neighbor' if our current state is bad
  1386. if (pRte->rte_State >= BAD)
  1387. {
  1388. Datagram[index++] = RTMP_NUM_HOPS_MASK;
  1389. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  1390. ("atalkRtmpSendRoutingData: Notifying neighbor of bad Rte - port %Z, Range %d.%d\n",
  1391. &pRte->rte_PortDesc->pd_AdapterKey,
  1392. pRte->rte_NwRange.anr_FirstNetwork,
  1393. pRte->rte_NwRange.anr_LastNetwork));
  1394. }
  1395. else
  1396. {
  1397. Datagram[index++] = pRte->rte_NumHops;
  1398. }
  1399. // Send an extended tuple, if the network range isn't ONE or the
  1400. // target port is an extended network.
  1401. // JH - Changed this so that an extended tuple is sent IFF the range
  1402. // isn't ONE
  1403. #if EXT_TUPLES_FOR_NON_EXTENDED_RANGE
  1404. if ((EXT_NET(pPortDesc)) &&
  1405. (pRte->rte_NwRange.anr_FirstNetwork != pRte->rte_NwRange.anr_LastNetwork))
  1406. #else
  1407. if (pRte->rte_NwRange.anr_FirstNetwork != pRte->rte_NwRange.anr_LastNetwork)
  1408. #endif
  1409. {
  1410. Datagram[index-1] |= RTMP_EXT_TUPLE_MASK;
  1411. PUTSHORT2SHORT(Datagram+index, pRte->rte_NwRange.anr_LastNetwork);
  1412. index += sizeof(SHORT);
  1413. Datagram[index++] = RTMP_VERSION;
  1414. }
  1415. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_INFO,
  1416. ("atalkRtmpSendRoutingData: Port %Z, Net '%d:%d', Distance %d\n",
  1417. &pPortDesc->pd_AdapterKey,
  1418. pRte->rte_NwRange.anr_FirstNetwork,
  1419. pRte->rte_NwRange.anr_LastNetwork,
  1420. pRte->rte_NumHops));
  1421. // Check if this datagram is full.
  1422. if ((index + RTMP_EXT_TUPLE_SIZE) >= MAX_DGRAM_SIZE)
  1423. {
  1424. pBuffDesc->bd_Length = (SHORT)index;
  1425. AllocNewBuffDesc = TRUE;
  1426. }
  1427. }
  1428. }
  1429. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  1430. // Close the current buffdesc
  1431. if (!AllocNewBuffDesc)
  1432. {
  1433. pBuffDesc->bd_Length = (SHORT)index;
  1434. }
  1435. // We have a bunch of datagrams ready to be fired off. Make it so.
  1436. SendInfo.sc_TransmitCompletion = atalkRtmpSendComplete;
  1437. // SendInfo.sc_Ctx2 = NULL;
  1438. // SendInfo.sc_Ctx3 = NULL;
  1439. for (pBuffDesc = pBuffDescStart;
  1440. pBuffDesc != NULL;
  1441. pBuffDesc = pBuffDescStart)
  1442. {
  1443. ATALK_ERROR ErrorCode;
  1444. pBuffDescStart = pBuffDesc->bd_Next;
  1445. // Reset next pointer to be null, length is already correctly set.
  1446. pBuffDesc->bd_Next = NULL;
  1447. ASSERT(pBuffDesc->bd_Length > 0);
  1448. SendInfo.sc_Ctx1 = pBuffDesc;
  1449. if (!ATALK_SUCCESS(ErrorCode = AtalkDdpSend(pDdpAddr,
  1450. pDstAddr,
  1451. DDPPROTO_RTMPRESPONSEORDATA,
  1452. FALSE,
  1453. pBuffDesc,
  1454. NULL,
  1455. 0,
  1456. NULL,
  1457. &SendInfo)))
  1458. {
  1459. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  1460. ("atalkRtmpSendRoutingData: DdpSend failed %ld\n", ErrorCode));
  1461. AtalkFreeBuffDesc(pBuffDesc);
  1462. }
  1463. }
  1464. AtalkDdpDereference(pDdpAddr);
  1465. }
  1466. /*** atalkRtmpGetOrSetNetworkNumber
  1467. *
  1468. */
  1469. BOOLEAN
  1470. atalkRtmpGetOrSetNetworkNumber(
  1471. IN PPORT_DESCRIPTOR pPortDesc,
  1472. IN USHORT SuggestedNetwork
  1473. )
  1474. {
  1475. int i;
  1476. ATALK_ERROR ErrorCode;
  1477. ATALK_ADDR SrcAddr, DstAddr;
  1478. PBUFFER_DESC pBuffDesc;
  1479. KIRQL OldIrql;
  1480. BOOLEAN RetCode = TRUE;
  1481. SEND_COMPL_INFO SendInfo;
  1482. // If we find the network number of the network, use that and ignore the
  1483. // one passed in. Otherwise use the one passed in, unless it is UNKOWN (0)
  1484. // in which case it is an error case. This is used only for non-extended
  1485. // networks
  1486. ASSERT (!EXT_NET(pPortDesc));
  1487. SrcAddr.ata_Network = UNKNOWN_NETWORK;
  1488. SrcAddr.ata_Node = pPortDesc->pd_RouterNode->an_NodeAddr.atn_Node;
  1489. SrcAddr.ata_Socket = RTMP_SOCKET;
  1490. DstAddr.ata_Network = UNKNOWN_NETWORK;
  1491. DstAddr.ata_Node = ATALK_BROADCAST_NODE;
  1492. DstAddr.ata_Socket = RTMP_SOCKET;
  1493. // Send off a bunch of broadcasts and see if we get to know the network #
  1494. KeClearEvent(&pPortDesc->pd_SeenRouterEvent);
  1495. SendInfo.sc_TransmitCompletion = atalkRtmpSendComplete;
  1496. // SendInfo.sc_Ctx2 = NULL;
  1497. // SendInfo.sc_Ctx3 = NULL;
  1498. for (i = 0;
  1499. (i < RTMP_NUM_REQUESTS) && !(pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY);
  1500. i++)
  1501. {
  1502. if ((pBuffDesc = AtalkAllocBuffDesc(NULL,
  1503. RTMP_REQ_DATAGRAM_SIZE,
  1504. BD_CHAR_BUFFER | BD_FREE_BUFFER)) == NULL)
  1505. {
  1506. RetCode = FALSE;
  1507. break;
  1508. }
  1509. // Set buffer/size
  1510. pBuffDesc->bd_CharBuffer[0] = RTMP_REQUEST;
  1511. AtalkSetSizeOfBuffDescData(pBuffDesc, RTMP_REQ_DATAGRAM_SIZE);
  1512. SendInfo.sc_Ctx1 = pBuffDesc;
  1513. ErrorCode = AtalkDdpTransmit(pPortDesc,
  1514. &SrcAddr,
  1515. &DstAddr,
  1516. DDPPROTO_RTMPREQUEST,
  1517. pBuffDesc,
  1518. NULL,
  1519. 0,
  1520. 0,
  1521. NULL,
  1522. NULL,
  1523. &SendInfo);
  1524. if (!ATALK_SUCCESS(ErrorCode))
  1525. {
  1526. DBGPRINT(DBG_COMP_RTMP, DBG_LEVEL_ERR,
  1527. ("atalkRtmpGetOrSetNetworkNumber: DdpTransmit failed %ld\n", ErrorCode));
  1528. AtalkFreeBuffDesc(pBuffDesc);
  1529. RetCode = FALSE;
  1530. break;
  1531. }
  1532. if (AtalkWaitTE(&pPortDesc->pd_SeenRouterEvent, RTMP_REQUEST_WAIT))
  1533. break;
  1534. }
  1535. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  1536. // If we get an answer, we are done
  1537. if (pPortDesc->pd_Flags & PD_SEEN_ROUTER_RECENTLY)
  1538. {
  1539. if ((SuggestedNetwork != UNKNOWN_NETWORK) &&
  1540. (pPortDesc->pd_NetworkRange.anr_FirstNetwork != SuggestedNetwork))
  1541. {
  1542. LOG_ERRORONPORT(pPortDesc,
  1543. EVENT_ATALK_NETNUMBERCONFLICT,
  1544. 0,
  1545. NULL,
  1546. 0);
  1547. }
  1548. }
  1549. // If we did not get an answer, then we better have a good suggested
  1550. // network passed in
  1551. else if (SuggestedNetwork == UNKNOWN_NETWORK)
  1552. {
  1553. LOG_ERRORONPORT(pPortDesc,
  1554. EVENT_ATALK_INVALID_NETRANGE,
  1555. 0,
  1556. NULL,
  1557. 0);
  1558. RetCode = FALSE;
  1559. }
  1560. else
  1561. {
  1562. pPortDesc->pd_NetworkRange.anr_FirstNetwork =
  1563. pPortDesc->pd_NetworkRange.anr_LastNetwork = SuggestedNetwork;
  1564. }
  1565. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  1566. return RetCode;
  1567. }
  1568. /*** atalkRtmpComplete
  1569. *
  1570. */
  1571. VOID FASTCALL
  1572. atalkRtmpSendComplete(
  1573. IN NDIS_STATUS Status,
  1574. IN PSEND_COMPL_INFO pSendInfo
  1575. )
  1576. {
  1577. AtalkFreeBuffDesc((PBUFFER_DESC)(pSendInfo->sc_Ctx1));
  1578. }
  1579. #if DBG
  1580. PCHAR atalkRteStates[] = { "Eh ?", "GOOD", "SUSPECT", "BAD", "UGLY" };
  1581. VOID
  1582. AtalkRtmpDumpTable(
  1583. VOID
  1584. )
  1585. {
  1586. int i;
  1587. PRTE pRte;
  1588. if (AtalkRoutingTable == NULL)
  1589. return;
  1590. ACQUIRE_SPIN_LOCK_DPC(&AtalkRteLock);
  1591. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL, ("RECENT ROUTE CACHE:\n"));
  1592. for (i = 0; (AtalkRecentRoutes != NULL) && (i < NUM_RECENT_ROUTES); i ++)
  1593. {
  1594. if ((pRte = AtalkRecentRoutes[i]) != NULL)
  1595. {
  1596. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  1597. ("Port %Z Hops %d Range %4d.%4d Router %4d.%3d Flags %x Ref %2d %s\n",
  1598. &pRte->rte_PortDesc->pd_AdapterKey,
  1599. pRte->rte_NumHops,
  1600. pRte->rte_NwRange.anr_FirstNetwork,
  1601. pRte->rte_NwRange.anr_LastNetwork,
  1602. pRte->rte_NextRouter.atn_Network,
  1603. pRte->rte_NextRouter.atn_Node,
  1604. pRte->rte_Flags,
  1605. pRte->rte_RefCount,
  1606. atalkRteStates[pRte->rte_State]));
  1607. }
  1608. }
  1609. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL, ("ROUTINGTABLE:\n"));
  1610. for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i ++)
  1611. {
  1612. for (pRte = AtalkRoutingTable[i]; pRte != NULL; pRte = pRte->rte_Next)
  1613. {
  1614. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  1615. ("Port %Z Hops %d Range %4d.%4d Router %4d.%3d Flags %x Ref %2d %s\n",
  1616. &pRte->rte_PortDesc->pd_AdapterKey,
  1617. pRte->rte_NumHops,
  1618. pRte->rte_NwRange.anr_FirstNetwork,
  1619. pRte->rte_NwRange.anr_LastNetwork,
  1620. pRte->rte_NextRouter.atn_Network,
  1621. pRte->rte_NextRouter.atn_Node,
  1622. pRte->rte_Flags,
  1623. pRte->rte_RefCount,
  1624. atalkRteStates[pRte->rte_State]));
  1625. }
  1626. }
  1627. RELEASE_SPIN_LOCK_DPC(&AtalkRteLock);
  1628. }
  1629. #endif
  1630.