Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

685 lines
18 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. mcap.c
  5. Abstract:
  6. ARP1394 MCAP protocol code.
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. josephj 10-01-99 Created
  11. Notes:
  12. --*/
  13. #include <precomp.h>
  14. //
  15. // File-specific debugging defaults.
  16. //
  17. #define TM_CURRENT TM_MCAP
  18. //=========================================================================
  19. // L O C A L P R O T O T Y P E S
  20. //=========================================================================
  21. NDIS_STATUS
  22. arpParseMcapPkt(
  23. IN PIP1394_MCAP_PKT pMcapPkt,
  24. IN UINT cbBufferSize,
  25. OUT PIP1394_MCAP_PKT_INFO pPktInfo
  26. );
  27. VOID
  28. arpProcessMcapAdvertise(
  29. PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  30. PIP1394_MCAP_PKT_INFO pPktInfo,
  31. PRM_STACK_RECORD pSR
  32. );
  33. VOID
  34. arpProcessMcapSolicit(
  35. PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  36. PIP1394_MCAP_PKT_INFO pPktInfo,
  37. PRM_STACK_RECORD pSR
  38. );
  39. VOID
  40. arpUpdateMcapInfo(
  41. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  42. IN PIP1394_MCAP_PKT_INFO pPktInfo,
  43. PRM_STACK_RECORD pSR
  44. );
  45. NDIS_STATUS
  46. arpParseMcapPkt(
  47. IN PIP1394_MCAP_PKT pMcapPkt,
  48. IN UINT cbBufferSize,
  49. OUT PIP1394_MCAP_PKT_INFO pPktInfo
  50. );
  51. NDIS_STATUS
  52. arpParseMcapPkt(
  53. IN PIP1394_MCAP_PKT pMcapPkt,
  54. IN UINT cbBufferSize,
  55. OUT PIP1394_MCAP_PKT_INFO pPktInfo
  56. )
  57. /*++
  58. Routine Description:
  59. Parse the contents of IP/1394 MCAP packet data starting at
  60. pMcapPkt. Place the results into pPktInfo.
  61. Arguments:
  62. pMcapPkt - Contains the unaligned contents of an ip/1394 MCAP Pkt.
  63. pPktInfo - Unitialized structure to be filled with the parsed contents of the
  64. pkt.
  65. Return Value:
  66. NDIS_STATUS_FAILURE if the parse failed (typically because of invalid pkt
  67. contents.)
  68. NDIS_STATUS_SUCCESS on successful parsing.
  69. --*/
  70. {
  71. ENTER("arpParseMcapPkt", 0x95175d5a)
  72. NDIS_STATUS Status;
  73. DBGSTMT(CHAR *szError = "General failure";)
  74. Status = NDIS_STATUS_FAILURE;
  75. do
  76. {
  77. UINT OpCode; // MCAP op code (solicit/advertise)
  78. UINT Length; // Length of valid part of packet, including the encap header.
  79. UINT NumGds; // Number of group_descriptors;
  80. // Minimum size.
  81. //
  82. if (cbBufferSize < FIELD_OFFSET(IP1394_MCAP_PKT, group_descriptors))
  83. {
  84. DBGSTMT(szError = "Packet too small";)
  85. break;
  86. }
  87. // Ethertype
  88. //
  89. if (pMcapPkt->header.EtherType != H2N_USHORT(NIC1394_ETHERTYPE_MCAP))
  90. {
  91. DBGSTMT(szError = "header.EtherType!=MCAP";)
  92. break;
  93. }
  94. // length
  95. //
  96. {
  97. // pMcapPkt->length is the length of packet excluding the unfragmented
  98. // header.
  99. //
  100. Length = (ULONG) N2H_USHORT(pMcapPkt->length) + sizeof(pMcapPkt->header);
  101. if (Length > cbBufferSize)
  102. {
  103. DBGSTMT(szError = "Length field too large";)
  104. break;
  105. }
  106. // Note: it's valid to have zero group descriptors.
  107. //
  108. if (Length < FIELD_OFFSET(IP1394_MCAP_PKT, group_descriptors))
  109. {
  110. DBGSTMT(szError = "Length field too small";)
  111. break;
  112. }
  113. }
  114. // reserved field
  115. //
  116. if (pMcapPkt->reserved != 0)
  117. {
  118. DBGSTMT(szError = "reserved != 0";)
  119. break;
  120. }
  121. // Opcode
  122. //
  123. {
  124. OpCode = N2H_USHORT(pMcapPkt->opcode);
  125. if ( OpCode != IP1394_MCAP_OP_ADVERTISE
  126. && OpCode != IP1394_MCAP_OP_SOLICIT)
  127. {
  128. DBGSTMT(szError = "Invalid opcode";)
  129. break;
  130. }
  131. }
  132. // Now we check the descriptors
  133. //
  134. {
  135. PIP1394_MCAP_GD pGd;
  136. DBGSTMT(PIP1394_MCAP_GD pGdEnd;)
  137. UINT u;
  138. // Note: we've already verified that Length is large enough.
  139. //
  140. NumGds = (Length - FIELD_OFFSET(IP1394_MCAP_PKT, group_descriptors))
  141. / sizeof(IP1394_MCAP_GD);
  142. pGd = pMcapPkt->group_descriptors;
  143. DBGSTMT(pGdEnd = (PIP1394_MCAP_GD) (((PUCHAR) pMcapPkt) + cbBufferSize);)
  144. for (u=NumGds; u>0; u--, pGd++)
  145. {
  146. IP1394_MCAP_GD Gd;
  147. ASSERT(pGd < pGdEnd);
  148. Gd = *pGd; // Unaligned struct copy.
  149. if (Gd.length != sizeof(Gd))
  150. {
  151. // bad length
  152. //
  153. DBGSTMT(szError = "Bad GD: bad length";)
  154. break;
  155. }
  156. if (Gd.type != IP1394_MCAP_GD_TYPE_V1)
  157. {
  158. // bad type
  159. //
  160. DBGSTMT(szError = "Bad GD: bad type";)
  161. break;
  162. }
  163. if (Gd.reserved != 0)
  164. {
  165. // bad reserved
  166. //
  167. DBGSTMT(szError = "Bad GD: bad reserved";)
  168. break;
  169. }
  170. if (Gd.channel > 63)
  171. {
  172. // bad channel
  173. //
  174. DBGSTMT(szError = "Bad GD: bad channel";)
  175. break;
  176. }
  177. // We don't check speed code to interop with unknown speeds.
  178. // (we map unknown speeds to the highest speed code we know about.
  179. if (Gd.reserved2 != 0)
  180. {
  181. // bad reserved2
  182. //
  183. DBGSTMT(szError = "Bad GD: bad reserved2";)
  184. break;
  185. }
  186. if (Gd.bandwidth != 0)
  187. {
  188. // bad bandwidth
  189. //
  190. DBGSTMT(szError = "Bad GD: bad bandwidth";)
  191. break;
  192. }
  193. {
  194. UINT Addr = H2N_ULONG(Gd.group_address);
  195. if ( (Addr & 0xf0000000) != 0xe0000000)
  196. {
  197. // Address is not class D
  198. //
  199. DBGSTMT(szError = "Bad GD: address not class D";)
  200. break;
  201. }
  202. if (Addr == 0xe0000001 || Addr == 0xe0000002)
  203. {
  204. // 224.0.0.1 and 224.0.0.2 must be sent on the broadcast
  205. // channel
  206. //
  207. DBGSTMT(szError = "Bad GD: Address 224.0.0.1 or 2";)
  208. break;
  209. }
  210. }
  211. }
  212. if (u!=0)
  213. {
  214. break;
  215. }
  216. }
  217. //
  218. // Pkt appears valid, let's fill out the parsed information....
  219. //
  220. ARP_ZEROSTRUCT(pPktInfo);
  221. pPktInfo->NumGroups = NumGds;
  222. pPktInfo->SenderNodeID = N2H_USHORT(pMcapPkt->header.NodeId);
  223. pPktInfo->OpCode = OpCode;
  224. // Parse the group descriptors...
  225. // If required, dynamically allocate space for the descriptors,
  226. // otherwise we use pPktInfo->GdSpace;
  227. //
  228. {
  229. PIP1394_MCAP_GD pGd;
  230. PIP1394_MCAP_GD_INFO pGdi;
  231. UINT cb = NumGds * sizeof(*pGdi);
  232. UINT u;
  233. if (cb <= sizeof(pPktInfo->GdiSpace))
  234. {
  235. pGdi = pPktInfo->GdiSpace;
  236. }
  237. else
  238. {
  239. NdisAllocateMemoryWithTag(&pGdi, cb, MTAG_MCAP_GD);
  240. if (pGdi == NULL)
  241. {
  242. DBGSTMT(szError = "Allocation Failure";)
  243. Status = NDIS_STATUS_RESOURCES;
  244. break;
  245. }
  246. }
  247. pPktInfo->pGdis = pGdi;
  248. // Now parse...
  249. //
  250. pGd = pMcapPkt->group_descriptors;
  251. for (u=NumGds; u>0; u--, pGd++, pGdi++)
  252. {
  253. pGdi->Expiration = pGd->expiration;
  254. pGdi->Channel = pGd->channel;
  255. pGdi->SpeedCode = pGd->speed;
  256. pGdi->GroupAddress = pGd->group_address; // Leave in Network order
  257. if (pGdi->Channel >= ARP_NUM_CHANNELS)
  258. {
  259. TR_INFO(("Bad channel in GD 0x%p\n", pGdi));
  260. continue;
  261. }
  262. //
  263. // Although RFC doesn't stipulate a max expiry time, we
  264. // cap it ourselves, in case this is a rogue packet.
  265. //
  266. #define MAX_EXPIRATION 120
  267. if (pGdi->Expiration >= MAX_EXPIRATION)
  268. {
  269. TR_INFO(("Capping expiry time to %d sec\n", MAX_EXPIRATION));
  270. pGdi->Expiration = MAX_EXPIRATION;
  271. continue;
  272. }
  273. if (pGdi->SpeedCode > SCODE_3200_RATE)
  274. {
  275. //
  276. // This is either a bad value, or a rate higher than we know
  277. // about. We can't distinguish between the two, so we just set
  278. // the speed to the highest we know about.
  279. //
  280. pGdi->SpeedCode = SCODE_3200_RATE;
  281. }
  282. }
  283. }
  284. Status = NDIS_STATUS_SUCCESS;
  285. } while (FALSE);
  286. if (FAIL(Status))
  287. {
  288. TR_WARN(("Bad mcap pkt data at 0x%p (%s)\n", pMcapPkt, szError));
  289. }
  290. else
  291. {
  292. #if DBG
  293. UINT Addr = 0;
  294. UINT Channel = 0;
  295. UINT Exp = 0;
  296. PUCHAR pc = (PUCHAR) &Addr;
  297. if (pPktInfo->NumGroups!=0)
  298. {
  299. Addr = pPktInfo->pGdis[0].GroupAddress;
  300. Channel = pPktInfo->pGdis[0].Channel;
  301. Exp = pPktInfo->pGdis[0].Expiration;
  302. }
  303. #endif // DBG
  304. TR_WARN(("Received MCAP PKT. NodeId=0x%04lx NumGrps=%lu."
  305. " 1st=(Grp=%lu.%lu.%lu.%lu, Ch=%lu, TTL=%lu)\n",
  306. pPktInfo->SenderNodeID,
  307. pPktInfo->NumGroups,
  308. pc[0], pc[1], pc[2], pc[3],
  309. Channel,
  310. Exp
  311. ));
  312. }
  313. EXIT()
  314. return Status;
  315. }
  316. NDIS_STATUS
  317. arpCreateMcapPkt(
  318. IN PARP1394_INTERFACE pIF,
  319. IN PIP1394_MCAP_PKT_INFO pPktInfo,
  320. OUT PNDIS_PACKET *ppNdisPacket,
  321. PRM_STACK_RECORD pSR
  322. )
  323. /*++
  324. Routine Description:
  325. Use information in pPktInfo to allocate and initialize an mcap packet.
  326. Arguments:
  327. pPktInfo - Parsed version of the arp request/response packet.
  328. ppNdisPacket - Points to a place to store a pointer to the allocated packet.
  329. Return Value:
  330. NDIS_STATUS_RESOURCES - If we couldn't allocate the packet.
  331. NDIS_STATUS_SUCCESS - on success.
  332. --*/
  333. {
  334. UINT NumGroups;
  335. UINT Length;
  336. NDIS_STATUS Status;
  337. PIP1394_MCAP_PKT pPktData;
  338. PIP1394_MCAP_GD pGd;
  339. NumGroups = pPktInfo->NumGroups;
  340. Length = FIELD_OFFSET(IP1394_MCAP_PKT, group_descriptors);
  341. Length += NumGroups * sizeof(IP1394_MCAP_GD);
  342. Status = arpAllocateControlPacket(
  343. pIF,
  344. Length,
  345. ARP1394_PACKET_FLAGS_MCAP,
  346. ppNdisPacket,
  347. &pPktData,
  348. pSR
  349. );
  350. if (FAIL(Status)) return Status; // ***** EARLY RETURN ******
  351. // Can't use ARP_ZEROSTRUCT because NumGroups may be zero.
  352. //
  353. NdisZeroMemory(pPktData, Length);
  354. pPktData->header.EtherType = H2N_USHORT(NIC1394_ETHERTYPE_MCAP);
  355. pPktData->opcode = (UCHAR)pPktInfo->OpCode;
  356. Length -= sizeof(pPktData->header); // Skip the header.
  357. pPktData->length = H2N_USHORT(Length);
  358. // Construct the group descriptors.
  359. //
  360. if (NumGroups)
  361. {
  362. PIP1394_MCAP_GD_INFO pGdi = pPktInfo->pGdis;
  363. PIP1394_MCAP_GD pGd = pPktData->group_descriptors;
  364. for(;NumGroups; pGdi++, pGd++, NumGroups--)
  365. {
  366. ARP_ZEROSTRUCT(pGd);
  367. pGd->length = (UCHAR) sizeof(*pGd);
  368. pGd->expiration = (UCHAR) pGdi->Expiration;
  369. pGd->channel = (UCHAR) pGdi->Channel;
  370. pGd->speed = (UCHAR) pGdi->SpeedCode;
  371. pGd->group_address = pGdi->GroupAddress;
  372. }
  373. }
  374. return NDIS_STATUS_SUCCESS;
  375. }
  376. #if 0
  377. // Parsed version of the IP/1394 MCAP Group Descriptor
  378. //
  379. typedef struct
  380. {
  381. UINT Expiration;
  382. UINT Channel;
  383. UINT SpeedCode;
  384. IP_ADDRESS GroupAddress;
  385. } IP1394_MCAP_GD_INFO, * PIP1394_MCAP_GD_INFO;
  386. // Parsed version of an IP/1394 MCAP packet.
  387. //
  388. typedef struct
  389. {
  390. UINT SenderNodeID;
  391. UINT OpCode;
  392. UINT NumGroups;
  393. PIP1394_MCAP_GD_INFO pGdis;
  394. // Space for storing up-to 4 GD_INFOs
  395. //
  396. IP1394_MCAP_GD_INFO GdiSpace[4];
  397. } IP1394_MCAP_PKT_INFO, *PIP1394_MCAP_PKT_INFO;
  398. #endif // 0
  399. VOID
  400. arpUpdateMcapInfo(
  401. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  402. IN PIP1394_MCAP_PKT_INFO pPktInfo,
  403. PRM_STACK_RECORD pSR
  404. )
  405. {
  406. ENTER("arpUpdateMcapInfo", 0xcac15343)
  407. PIP1394_MCAP_GD_INFO pGdi;
  408. UINT NumGroups;
  409. UINT Current;
  410. UINT NodeId;
  411. RM_DECLARE_STACK_RECORD(sr)
  412. RM_ASSERT_OBJUNLOCKED(&pIF->Hdr, pSR);
  413. // Get the current time (in seconds).
  414. //
  415. Current = arpGetSystemTime();
  416. //
  417. // Go through the group discriptors, updating our database.
  418. //
  419. NumGroups = pPktInfo->NumGroups;
  420. pGdi = pPktInfo->pGdis;
  421. NodeId = pPktInfo->SenderNodeID;
  422. for(;NumGroups; pGdi++, NumGroups--)
  423. {
  424. UINT Expiration = pGdi->Expiration;
  425. UINT Channel = pGdi->Channel;
  426. IP_ADDRESS GroupAddress = pGdi->GroupAddress;
  427. PMCAP_CHANNEL_INFO pMci;
  428. //
  429. // Process this group descriptor.
  430. //
  431. if (Channel >= ARP_NUM_CHANNELS)
  432. {
  433. ASSERT(FALSE); // we should have already screened this value.
  434. continue;
  435. }
  436. LOCKOBJ(pIF, &sr);
  437. pMci = &pIF->mcapinfo.rgChannelInfo[Channel];
  438. pMci->Channel = Channel;
  439. pMci->GroupAddress = GroupAddress;
  440. pMci->UpdateTime = Current;
  441. pMci->ExpieryTime = Current + Expiration; // Expiration is in seconds.
  442. pMci->Flags = 0; // Reset flags.
  443. pMci->NodeId = NodeId; // TODO: check if existing node id is higher?
  444. UNLOCKOBJ(pIF, &sr);
  445. }
  446. RM_ASSERT_OBJUNLOCKED(&pIF->Hdr, pSR);
  447. }
  448. VOID
  449. arpProcessMcapPkt(
  450. PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  451. PIP1394_MCAP_PKT pMcapPkt,
  452. UINT cbBufferSize
  453. )
  454. {
  455. NDIS_STATUS Status;
  456. IP1394_MCAP_PKT_INFO PktInfo;
  457. ENTER("arpProcessMcapPkt", 0xc5ba8005)
  458. RM_DECLARE_STACK_RECORD(sr)
  459. DBGMARK(0x3cfaf454);
  460. Status = arpParseMcapPkt(
  461. pMcapPkt,
  462. cbBufferSize,
  463. &PktInfo
  464. );
  465. if (!FAIL(Status))
  466. {
  467. if (PktInfo.OpCode == IP1394_MCAP_OP_ADVERTISE)
  468. {
  469. arpProcessMcapAdvertise(pIF, &PktInfo, &sr);
  470. }
  471. else
  472. {
  473. ASSERT(PktInfo.OpCode == IP1394_MCAP_OP_SOLICIT);
  474. arpProcessMcapSolicit(pIF, &PktInfo, &sr);
  475. }
  476. }
  477. RM_ASSERT_CLEAR(&sr);
  478. EXIT()
  479. }
  480. VOID
  481. arpProcessMcapAdvertise(
  482. PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  483. PIP1394_MCAP_PKT_INFO pPktInfo,
  484. PRM_STACK_RECORD pSR
  485. )
  486. {
  487. //
  488. // Update our database.
  489. //
  490. arpUpdateMcapInfo(
  491. pIF, // NOLOCKIN NOLOCKOUT
  492. pPktInfo,
  493. pSR
  494. );
  495. }
  496. VOID
  497. arpProcessMcapSolicit(
  498. PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  499. PIP1394_MCAP_PKT_INFO pPktInfo,
  500. PRM_STACK_RECORD pSR
  501. )
  502. {
  503. //
  504. // We ignore solicit messages.
  505. //
  506. //
  507. }
  508. MYBOOL
  509. arpIsActiveMcapChannel(
  510. PMCAP_CHANNEL_INFO pMci,
  511. UINT CurrentTime
  512. )
  513. {
  514. ENTER("IsActiveMcapChannel", 0x0)
  515. MYBOOL fOk = TRUE;
  516. // Check update time.
  517. //
  518. #define ARP_MAX_MCAP_UPDATE_INTERVAL 60
  519. if ((pMci->UpdateTime+ARP_MAX_MCAP_UPDATE_INTERVAL) < CurrentTime)
  520. {
  521. TR_WARN(("McapDB: channel %lu update time crossed.\n",
  522. pMci->Channel
  523. ));
  524. fOk = FALSE;
  525. }
  526. // Check expire time.
  527. //
  528. if (pMci->ExpieryTime <= CurrentTime)
  529. {
  530. TR_WARN(("McapDB: channel %lu time expired.\n",
  531. pMci->Channel
  532. ));
  533. fOk = FALSE;
  534. }
  535. return fOk;
  536. }
  537. VOID
  538. arpLocallyUpdateMcapInfo(
  539. PARP1394_INTERFACE pIF,
  540. UINT Channel,
  541. UINT GroupAddress,
  542. UINT CurrentTime,
  543. PRM_STACK_RECORD pSR
  544. )
  545. {
  546. ENTER("arpLocallyUpdateMcapInfo", 0x0)
  547. PMCAP_CHANNEL_INFO pMci;
  548. LOCKOBJ(pIF, pSR);
  549. pMci = &pIF->mcapinfo.rgChannelInfo[Channel];
  550. pMci->Channel = Channel;
  551. pMci->GroupAddress = GroupAddress;
  552. pMci->UpdateTime = CurrentTime;
  553. pMci->ExpieryTime = CurrentTime + 60; // Expiration is in seconds.
  554. pMci->Flags = 0; // Reset flags.
  555. pMci->NodeId = 0; // NodeId; // TODO: get real node id.
  556. UNLOCKOBJ(pIF, pSR);
  557. }