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.

930 lines
31 KiB

  1. //=============================================================================
  2. // FILE: SPParser.cpp
  3. //
  4. // Description: DirectPlay Service Provider Parser
  5. //
  6. //
  7. // Modification History:
  8. //
  9. // Michael Milirud 08/Aug/2000 Created
  10. //=============================================================================
  11. //#define FRAME_NAMES
  12. //#define FRAME_DROPS
  13. //==================//
  14. // Standard headers //
  15. //==================//
  16. #include <winsock2.h>
  17. #include <wsipx.h>
  18. #include <ws2tcpip.h>
  19. #include <tchar.h>
  20. //=====================//
  21. // Proprietary headers //
  22. //=====================//
  23. #include "dpaddr.h" // DPNA_DEFAULT_PORT definition
  24. // Prototypes
  25. #include "SPParser.hpp"
  26. namespace DPlaySP
  27. {
  28. // SP protocol header
  29. #include "MessageStructures.h"
  30. } // DPlaySP namespace
  31. namespace
  32. {
  33. HPROTOCOL g_hSPProtocol;
  34. //=============================//
  35. // Return Address Family field //-----------------------------------------------------------------------------------
  36. //=============================//
  37. LABELED_BYTE arr_RetAddrFamilyByteLabels[] = { { AF_IPX, "IPX protocol" },
  38. { AF_INET, "IPv4 protocol" },
  39. { AF_INET6, "IPv6 protocol" } };
  40. SET LabeledRetAddrFamilyByteSet = { sizeof(arr_RetAddrFamilyByteLabels) / sizeof(LABELED_BYTE), arr_RetAddrFamilyByteLabels };
  41. //================//
  42. // Data Tag field //------------------------------------------------------------------------------------------------
  43. //================//
  44. LABELED_BYTE arr_CommandByteLabels[] = { { ENUM_DATA_KIND, "Enumeration Query" },
  45. { ENUM_RESPONSE_DATA_KIND, "Response to Enumeration Query" },
  46. { PROXIED_ENUM_DATA_KIND, "Proxied Enumeration Query" } };
  47. SET LabeledCommandByteSet = { sizeof(arr_CommandByteLabels) / sizeof(LABELED_BYTE), arr_CommandByteLabels };
  48. ////////////////////////////////
  49. // Custom Property Formatters //=====================================================================================
  50. ////////////////////////////////
  51. // DESCRIPTION: Custom description formatter for the Service Provider packet summary
  52. //
  53. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  54. //
  55. // RETURNS: NOTHING
  56. //
  57. VOID WINAPIV FormatPropertyInstance_SPSummary( LPPROPERTYINST io_pProperyInstance )
  58. {
  59. using namespace DPlaySP;
  60. // Check what SP frame we are dealing with
  61. const PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(io_pProperyInstance->lpData);
  62. //
  63. switch ( rSPFrame.GenericHeader.bSPCommandByte )
  64. {
  65. case ENUM_DATA_KIND: // Service Provider Query
  66. {
  67. strcpy(io_pProperyInstance->szPropertyText, "Enumeration Request");
  68. break;
  69. }
  70. case ENUM_RESPONSE_DATA_KIND: // Service Provider Response
  71. {
  72. strcpy(io_pProperyInstance->szPropertyText, "Enumeration Response");
  73. break;
  74. }
  75. case PROXIED_ENUM_DATA_KIND: // Service Provider Proxied Query
  76. {
  77. strcpy(io_pProperyInstance->szPropertyText, "Proxied Enumeration Request");
  78. break;
  79. }
  80. default:
  81. {
  82. strcpy(io_pProperyInstance->szPropertyText, "User Data");
  83. break;
  84. }
  85. }
  86. } // FormatPropertyInstance_SPSummary
  87. //==================//
  88. // Properties table //-----------------------------------------------------------------------------------------------
  89. //==================//
  90. PROPERTYINFO g_arr_SPProperties[] =
  91. {
  92. // SP packet summary property (SP_SUMMARY)
  93. {
  94. 0, // handle placeholder (MBZ)
  95. 0, // reserved (MBZ)
  96. "", // label
  97. "DPlay Service Provider packet", // status-bar comment
  98. PROP_TYPE_SUMMARY, // data type
  99. PROP_QUAL_NONE, // data type qualifier
  100. NULL, // labeled bit set
  101. 512, // description's maximum length
  102. FormatPropertyInstance_SPSummary // generic formatter
  103. },
  104. // Leading Zero property (SP_LEADZERO)
  105. {
  106. 0, // handle placeholder (MBZ)
  107. 0, // reserved (MBZ)
  108. "Leading zero tag", // label
  109. "Leading zero tag field", // status-bar comment
  110. PROP_TYPE_BYTE, // data type
  111. PROP_QUAL_NONE, // data type qualifier.
  112. NULL, // labeled byte set
  113. 64, // description's maximum length
  114. FormatPropertyInstance // generic formatter
  115. },
  116. // Data Tag property (SP_COMMAND)
  117. {
  118. 0, // handle placeholder (MBZ)
  119. 0, // reserved (MBZ)
  120. "Command", // label
  121. "Command field", // status-bar comment
  122. PROP_TYPE_BYTE, // data type
  123. PROP_QUAL_LABELED_SET, // data type qualifier.
  124. &LabeledCommandByteSet, // labeled byte set
  125. 512, // description's maximum length
  126. FormatPropertyInstance // generic formatter
  127. },
  128. // Enumeration Key property (SP_ENUMPAYLOAD)
  129. {
  130. 0, // handle placeholder (MBZ)
  131. 0, // reserved (MBZ)
  132. "Enum Payload", // label
  133. "Enumeration Payload field", // status-bar comment
  134. PROP_TYPE_WORD, // data type
  135. PROP_QUAL_NONE, // data type qualifier.
  136. NULL, // labeled byte set
  137. 64, // description's maximum length
  138. FormatPropertyInstance // generic formatter
  139. },
  140. // Enumeration Key property (SP_ENUMKEY)
  141. {
  142. 0, // handle placeholder (MBZ)
  143. 0, // reserved (MBZ)
  144. "Enum Key", // label
  145. "Enumeration Key field", // status-bar comment
  146. PROP_TYPE_WORD, // data type
  147. PROP_QUAL_NONE, // data type qualifier.
  148. NULL, // labeled byte set
  149. 64, // description's maximum length
  150. FormatPropertyInstance // generic formatter
  151. },
  152. // Enumeration Response Key property (SP_ENUMRESPKEY)
  153. {
  154. 0, // handle placeholder (MBZ)
  155. 0, // reserved (MBZ)
  156. "Enum Response Key", // label
  157. "Enumeration Response Key", // status-bar comment
  158. PROP_TYPE_WORD, // data type
  159. PROP_QUAL_NONE, // data type qualifier.
  160. NULL, // labeled byte set
  161. 64, // description's maximum length
  162. FormatPropertyInstance // generic formatter
  163. },
  164. // Enumeration Response Key property (SP_RTTINDEX)
  165. {
  166. 0, // handle placeholder (MBZ)
  167. 0, // reserved (MBZ)
  168. "RTT Index", // label
  169. "RTT Index field", // status-bar comment
  170. PROP_TYPE_WORD, // data type
  171. PROP_QUAL_NONE, // data type qualifier.
  172. NULL, // labeled byte set
  173. 64, // description's maximum length
  174. FormatPropertyInstance // generic formatter
  175. },
  176. // Size of the return address property (SP_RETADDRSIZE)
  177. {
  178. 0, // handle placeholder (MBZ)
  179. 0, // reserved (MBZ)
  180. "Return Address's Size", // label
  181. "Size of the return address", // status-bar comment
  182. PROP_TYPE_BYTE, // data type
  183. PROP_QUAL_NONE, // data type qualifier.
  184. NULL, // labeled byte set
  185. 64, // description's maximum length
  186. FormatPropertyInstance // generic formatter
  187. },
  188. // Return Address Socket Family property (SP_RETADDRFAMILY)
  189. {
  190. 0, // handle placeholder (MBZ)
  191. 0, // reserved (MBZ)
  192. "Socket Family", // label
  193. "Socket Family field", // status-bar comment
  194. PROP_TYPE_WORD, // data type
  195. PROP_QUAL_LABELED_SET, // data type qualifier.
  196. &LabeledRetAddrFamilyByteSet, // labeled byte set
  197. 512, // description's maximum length
  198. FormatPropertyInstance // generic formatter
  199. },
  200. // Return Address Socket Family property (SP_RETADDR_IPX)
  201. {
  202. 0, // handle placeholder (MBZ)
  203. 0, // reserved (MBZ)
  204. "IPX Address", // label
  205. "IPX Address field", // status-bar comment
  206. PROP_TYPE_IPX_ADDRESS, // data type
  207. PROP_QUAL_NONE, // data type qualifier.
  208. NULL, // labeled byte set
  209. 64, // description's maximum length
  210. FormatPropertyInstance // generic formatter
  211. },
  212. // Return Address Socket (SP_RETADDRSOCKET_IPX)
  213. {
  214. 0, // handle placeholder (MBZ)
  215. 0, // reserved (MBZ)
  216. "Socket", // label
  217. "Socket field", // status-bar comment
  218. PROP_TYPE_WORD, // data type
  219. PROP_QUAL_NONE, // data type qualifier.
  220. NULL, // labeled byte set
  221. 64, // description's maximum length
  222. FormatPropertyInstance // generic formatter
  223. },
  224. // Return Address Socket Family property (SP_RETADDR_IP)
  225. {
  226. 0, // handle placeholder (MBZ)
  227. 0, // reserved (MBZ)
  228. "IP Address", // label
  229. "IP Address field", // status-bar comment
  230. PROP_TYPE_IP_ADDRESS, // data type
  231. PROP_QUAL_NONE, // data type qualifier.
  232. NULL, // labeled byte set
  233. 64, // description's maximum length
  234. FormatPropertyInstance // generic formatter
  235. },
  236. // Return Address Socket (SP_RETADDRPORT_IP)
  237. {
  238. 0, // handle placeholder (MBZ)
  239. 0, // reserved (MBZ)
  240. "Port", // label
  241. "Port field", // status-bar comment
  242. PROP_TYPE_WORD, // data type
  243. PROP_QUAL_NONE, // data type qualifier.
  244. NULL, // labeled byte set
  245. 64, // description's maximum length
  246. FormatPropertyInstance // generic formatter
  247. },
  248. // Return Address Socket Family property (SP_RETADDR_IPV6)
  249. {
  250. 0, // handle placeholder (MBZ)
  251. 0, // reserved (MBZ)
  252. "IPv6 Address", // label
  253. "IPv6 Address field", // status-bar comment
  254. PROP_TYPE_IP6_ADDRESS, // data type
  255. PROP_QUAL_NONE, // data type qualifier.
  256. NULL, // labeled byte set
  257. 64, // description's maximum length
  258. FormatPropertyInstance // generic formatter
  259. },
  260. // User Data (SP_USERDATA)
  261. {
  262. 0, // handle placeholder (MBZ)
  263. 0, // reserved (MBZ)
  264. "User Data", // label
  265. "User Data", // status-bar comment
  266. PROP_TYPE_RAW_DATA, // data type
  267. PROP_QUAL_NONE, // data type qualifier.
  268. NULL, // labeled bit set
  269. 64, // description's maximum length
  270. FormatPropertyInstance // generic formatter
  271. }
  272. };
  273. enum
  274. {
  275. nNUM_OF_SP_PROPS = sizeof(g_arr_SPProperties) / sizeof(PROPERTYINFO)
  276. };
  277. // Properties' indices
  278. enum
  279. {
  280. SP_SUMMARY = 0,
  281. SP_LEADZERO,
  282. SP_COMMAND,
  283. SP_ENUMPAYLOAD,
  284. SP_ENUMKEY,
  285. SP_ENUMRESPKEY,
  286. SP_RTTINDEX,
  287. SP_RETADDRSIZE,
  288. SP_RETADDRFAMILY,
  289. SP_RETADDR_IPX,
  290. SP_RETADDRSOCKET_IPX,
  291. SP_RETADDR_IP,
  292. SP_RETADDRPORT_IP,
  293. SP_RETADDR_IPV6,
  294. SP_USERDATA
  295. };
  296. // Platform independent memory accessor of big endian words
  297. inline WORD ReadBigEndianWord( BYTE* i_pbData )
  298. {
  299. return (*i_pbData << 8) | *(i_pbData+1);
  300. }
  301. // DESCRIPTION: DPlay packet validation predicate.
  302. //
  303. // ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
  304. // i_hPrevProtocol - Handle of the previous protocol.
  305. // i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
  306. // the data that the other parsers recognize.
  307. //
  308. // RETURNS: DPlay packet = TRUE; NOT a DPlay packet = FALSE
  309. //
  310. bool IsDPlayPacket( HFRAME i_hFrame, HPROTOCOL i_hPrevProtocol, LPBYTE i_pbMacFrame )
  311. {
  312. const PROTOCOLINFO* pPrevProtocolInfo = GetProtocolInfo(i_hPrevProtocol);
  313. DWORD dwPrevProtocolOffset = GetProtocolStartOffsetHandle(i_hFrame, i_hPrevProtocol);
  314. WORD wSrcPort, wDstPort;
  315. if ( strncmp(reinterpret_cast<const char*>(pPrevProtocolInfo->ProtocolName), "UDP", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  316. {
  317. // Extracting the source and destination ports of the packet from its UDP header
  318. wSrcPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset);
  319. wDstPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 2);
  320. }
  321. else if ( strncmp(reinterpret_cast<const char*>(pPrevProtocolInfo->ProtocolName), "IPX", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  322. {
  323. // Extracting the source and destination ports of the packet from its IPX header
  324. wSrcPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 16); // source address socket
  325. wDstPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 28); // destination address socket
  326. }
  327. else
  328. {
  329. // Should never happen!
  330. return false;
  331. }
  332. //===========//
  333. // Constants //
  334. //===========//
  335. //
  336. static bool bTriedRetrievingUserPorts = false;
  337. static bool bRetrievedUserPorts = false;
  338. static DWORD dwMinUserPort, dwMaxUserPort;
  339. // Retrieval from the registry is attempted only once
  340. if ( !bTriedRetrievingUserPorts )
  341. {
  342. bTriedRetrievingUserPorts = true;
  343. HKEY hKey = NULL;
  344. if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\DirectPlay\\Parsers"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  345. {
  346. DWORD dwType = NULL;
  347. DWORD dwCount = sizeof(DWORD);
  348. if (RegQueryValueEx(hKey, _T("MinUserPort"), NULL, &dwType, (LPBYTE)&dwMinUserPort, &dwCount) == ERROR_SUCCESS &&
  349. RegQueryValueEx(hKey, _T("MaxUserPort"), NULL, &dwType, (LPBYTE)&dwMaxUserPort, &dwCount) == ERROR_SUCCESS )
  350. {
  351. bRetrievedUserPorts = true;
  352. }
  353. RegCloseKey(hKey);
  354. }
  355. }
  356. if ( bRetrievedUserPorts &&
  357. ((wSrcPort >= dwMinUserPort) && (wSrcPort <= dwMaxUserPort)) &&
  358. ((wDstPort >= dwMinUserPort) && (wDstPort <= dwMaxUserPort)) )
  359. {
  360. // Is a valid DPlay packet
  361. return true;
  362. }
  363. // Make sure both endpoints are using the SP port range [2302, 2400], or the DPNServer port {6073}, or [MinUsePort, MaxUserPort] (if provided by the user)
  364. WORD wPort = wSrcPort;
  365. for ( int nPorts = 0; nPorts < 2; ++nPorts, wPort = wDstPort )
  366. {
  367. if (
  368. (
  369. !bRetrievedUserPorts ||
  370. (wPort < dwMinUserPort) ||
  371. (wPort > dwMaxUserPort)
  372. )
  373. &&
  374. (
  375. (wPort < BASE_DPLAY8_PORT) ||
  376. (wPort > MAX_DPLAY8_PORT)
  377. )
  378. &&
  379. (
  380. wPort != DPNA_DPNSVR_PORT
  381. )
  382. )
  383. {
  384. // Not a valid DPlay packet
  385. return false;
  386. }
  387. }
  388. // Is a valid DPlay packet
  389. return true;
  390. } // IsDPlayPacket
  391. } // anonymous namespace
  392. // DESCRIPTION: Creates and fills-in a properties database for the protocol.
  393. // Network Monitor uses this database to determine which properties the protocol supports.
  394. //
  395. // ARGUMENTS: i_hSPProtocol - The handle of the protocol provided by the Network Monitor.
  396. //
  397. // RETURNS: NOTHING
  398. //
  399. DPLAYPARSER_API VOID BHAPI SPRegister( HPROTOCOL i_hSPProtocol )
  400. {
  401. CreatePropertyDatabase(i_hSPProtocol, nNUM_OF_SP_PROPS);
  402. // Add the properties to the database
  403. for( int nProp=0; nProp < nNUM_OF_SP_PROPS; ++nProp )
  404. {
  405. AddProperty(i_hSPProtocol, &g_arr_SPProperties[nProp]);
  406. }
  407. } // SPRegister
  408. // DESCRIPTION: Frees the resources used to create the protocol property database.
  409. //
  410. // ARGUMENTS: i_hSPProtocol - The handle of the protocol provided by the Network Monitor.
  411. //
  412. // RETURNS: NOTHING
  413. //
  414. DPLAYPARSER_API VOID WINAPI SPDeregister( HPROTOCOL i_hProtocol )
  415. {
  416. DestroyPropertyDatabase(i_hProtocol);
  417. } // SPDeregister
  418. namespace
  419. {
  420. // DESCRIPTION: Parses the SP frame to find its size (in bytes) NOT including the user data
  421. //
  422. // ARGUMENTS: i_pbSPFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  423. // in the middle of a frame because a previous parser has claimed data before this parser.
  424. //
  425. // RETURNS: Size of the specified SP frame (in bytes)
  426. //
  427. int SPHeaderSize( LPBYTE i_pbSPFrame )
  428. {
  429. using namespace DPlaySP;
  430. // Check what SP frame we are dealing with
  431. const PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_pbSPFrame);
  432. //
  433. switch ( rSPFrame.GenericHeader.bSPCommandByte )
  434. {
  435. case ENUM_DATA_KIND: // Service Provider Query
  436. {
  437. return sizeof(rSPFrame.EnumDataHeader);
  438. }
  439. case ENUM_RESPONSE_DATA_KIND: // Service Provider Response
  440. {
  441. return sizeof(rSPFrame.EnumResponseDataHeader);
  442. }
  443. case PROXIED_ENUM_DATA_KIND: // Service Provider Proxied Query
  444. {
  445. return sizeof(rSPFrame.ProxiedEnumDataHeader);
  446. }
  447. default: // user data starting with a nonzero byte
  448. {
  449. return 0; // no header
  450. }
  451. }
  452. } // SPHeaderSize
  453. } // Anonymous namespace
  454. // DESCRIPTION: Indicates whether a piece of data is recognized as the protocol that the parser detects.
  455. //
  456. // ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
  457. // i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
  458. // the data that the other parsers recognize.
  459. // i_pbSPFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  460. // in the middle of a frame because a previous parser has claimed data before this parser.
  461. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  462. // when the parser must identify the first protocol in the frame. Can be one of the following:
  463. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  464. // i_dwBytesLeft - The remaining number of bytes from a location in the frame to the end of the frame.
  465. // i_hPrevProtocol - Handle of the previous protocol.
  466. // i_dwPrevProtOffset - Offset of the previous protocol (from the beginning of the frame).
  467. // o_pdwProtocolStatus - Protocol status indicator. Must be one of the following: PROTOCOL_STATUS_RECOGNIZED,
  468. // PROTOCOL_STATUS_NOT_RECOGNIZED, PROTOCOL_STATUS_CLAIMED, PROTOCOL_STATUS_NEXT_PROTOCOL.
  469. // o_phNextProtocol - Placeholder for the handle of the next protocol. This parameter is set when the parser identifies
  470. // the protocol that follows its own protocol.
  471. // io_pdwptrInstData - On input, a pointer to the instance data from the previous protocol.
  472. // On output, a pointer to the instance data for the current protocol.
  473. //
  474. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized parser data.
  475. // If the parser claims all the remaining data, the return value is NULL. If the function is unsuccessful, the return
  476. // value is the initial value of the i_pbSPFrame parameter.
  477. //
  478. DPLAYPARSER_API LPBYTE BHAPI SPRecognizeFrame( HFRAME i_hFrame,
  479. ULPBYTE i_upbMacFrame,
  480. ULPBYTE i_upbSPFrame,
  481. DWORD i_dwMacType,
  482. DWORD i_dwBytesLeft,
  483. HPROTOCOL i_hPrevProtocol,
  484. DWORD i_dwPrevProtOffset,
  485. LPDWORD o_pdwProtocolStatus,
  486. LPHPROTOCOL o_phNextProtocol,
  487. PDWORD_PTR io_pdwptrInstData )
  488. {
  489. using namespace DPlaySP;
  490. // Validate the amount of unclaimed data
  491. enum
  492. {
  493. nMIN_SPHeaderSize = sizeof(PREPEND_BUFFER::_GENERIC_HEADER)
  494. };
  495. // Validate the packet as DPlay SP type
  496. if ( (i_dwBytesLeft < nMIN_SPHeaderSize) ||
  497. !IsDPlayPacket(i_hFrame, i_hPrevProtocol, i_upbMacFrame) )
  498. {
  499. // Assume the unclaimed data is not recognizable
  500. *o_pdwProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
  501. return i_upbSPFrame;
  502. }
  503. //==========================//
  504. // Get the DPlay frame size //
  505. //==========================//
  506. const PROTOCOLINFO* pPrevProtocolInfo = GetProtocolInfo(i_hPrevProtocol);
  507. WORD wDPlayFrameSize = 0;
  508. if ( strncmp(reinterpret_cast<const char*>(pPrevProtocolInfo->ProtocolName), "UDP", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  509. {
  510. // Extracting the UDP frame size
  511. WORD wUDPFrameSize = ReadBigEndianWord(i_upbMacFrame + i_dwPrevProtOffset + 4);
  512. enum { nUDP_HEADER_SIZE = 8 };
  513. wDPlayFrameSize = wUDPFrameSize - nUDP_HEADER_SIZE;
  514. }
  515. else if ( strncmp(reinterpret_cast<const char*>(pPrevProtocolInfo->ProtocolName), "IPX", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  516. {
  517. // Extracting the IPX frame size
  518. WORD wIPXFrameSize = ReadBigEndianWord(i_upbMacFrame + i_dwPrevProtOffset + 2); // source address socket
  519. enum { nIPX_HEADER_SIZE = 30 };
  520. wDPlayFrameSize = wIPXFrameSize - nIPX_HEADER_SIZE;
  521. }
  522. else
  523. {
  524. ; // TODO: ASSERT HERE
  525. }
  526. // Pass along the size of the Transport frame
  527. DWORD_PTR dwptrTransportFrameSize = wDPlayFrameSize - SPHeaderSize(i_upbSPFrame);
  528. *io_pdwptrInstData = dwptrTransportFrameSize;
  529. const PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_upbSPFrame);
  530. if ( rSPFrame.GenericHeader.bSPLeadByte == SP_HEADER_LEAD_BYTE ) // SP packet
  531. {
  532. *o_pdwProtocolStatus = PROTOCOL_STATUS_RECOGNIZED;
  533. *o_phNextProtocol = NULL;
  534. }
  535. else // user data (DPlay v8 Transport packet)
  536. {
  537. // Notify NetMon about the handoff protocol
  538. *o_pdwProtocolStatus = PROTOCOL_STATUS_NEXT_PROTOCOL;
  539. *o_phNextProtocol = GetProtocolFromName("DPLAYTRANSPORT");
  540. return i_upbSPFrame;
  541. }
  542. // Claim the rest of the data
  543. return NULL;
  544. } // SPRecognizeFrame
  545. // DESCRIPTION: Maps the properties that exist in a piece of recognized data to specific locations.
  546. //
  547. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  548. // i_pbMacFram - Pointer to the first byte in the frame.
  549. // i_pbSPFrame - Pointer to the start of the recognized data.
  550. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  551. // when the parser must identify the first protocol in the frame. Can be one of the following:
  552. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  553. // i_dwBytesLeft - The remaining number of bytes in a frame (starting from the beginning of the recognized data).
  554. // i_hPrevProtocol - Handle of the previous protocol.
  555. // i_dwPrevProtOffset - Offset of the previous protocol (starting from the beginning of the frame).
  556. // i_dwptrInstData - Pointer to the instance data that the previous protocol provides.
  557. //
  558. // RETURNS: Must return NULL
  559. //
  560. DPLAYPARSER_API LPBYTE BHAPI SPAttachProperties( HFRAME i_hFrame,
  561. ULPBYTE i_upbMacFrame,
  562. ULPBYTE i_upbSPFrame,
  563. DWORD i_dwMacType,
  564. DWORD i_dwBytesLeft,
  565. HPROTOCOL i_hPrevProtocol,
  566. DWORD i_dwPrevProtOffset,
  567. DWORD_PTR i_dwptrInstData )
  568. {
  569. using namespace DPlaySP;
  570. //===================//
  571. // Attach Properties //
  572. //===================//
  573. // Summary line
  574. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_SUMMARY].hProperty,
  575. i_dwBytesLeft, i_upbSPFrame, 0, 0, 0);
  576. // Protection against NetMon
  577. if ( *i_upbSPFrame )
  578. {
  579. return NULL;
  580. }
  581. // Check what SP frame we are dealing with
  582. PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_upbSPFrame);
  583. // Leading Zero tag field
  584. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_LEADZERO].hProperty,
  585. sizeof(rSPFrame.GenericHeader.bSPLeadByte), &rSPFrame.GenericHeader.bSPLeadByte, 0, 1, 0);
  586. // Command field
  587. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_COMMAND].hProperty,
  588. sizeof(rSPFrame.GenericHeader.bSPCommandByte), &rSPFrame.GenericHeader.bSPCommandByte, 0, 1, 0);
  589. switch ( rSPFrame.GenericHeader.bSPCommandByte )
  590. {
  591. case ENUM_DATA_KIND: // Service Provider's Enumeration Request
  592. {
  593. // Enum payload field
  594. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_ENUMPAYLOAD].hProperty,
  595. sizeof(rSPFrame.EnumDataHeader.wEnumPayload), &rSPFrame.EnumDataHeader.wEnumPayload, 0, 1, 0);
  596. // Enum Key field
  597. DWORD dwEnumKey = rSPFrame.EnumDataHeader.wEnumPayload & ~ENUM_RTT_MASK;
  598. AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_ENUMKEY].hProperty,
  599. sizeof(rSPFrame.EnumDataHeader.wEnumPayload), &rSPFrame.EnumDataHeader.wEnumPayload,
  600. sizeof(dwEnumKey), &dwEnumKey,
  601. 0, 2, 0);
  602. // RTT index field
  603. BYTE byRTTIndex = rSPFrame.EnumDataHeader.wEnumPayload & ENUM_RTT_MASK;
  604. AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_RTTINDEX].hProperty,
  605. sizeof(rSPFrame.EnumDataHeader.wEnumPayload), &rSPFrame.EnumDataHeader.wEnumPayload,
  606. sizeof(byRTTIndex), &byRTTIndex,
  607. 0, 2, 0);
  608. break;
  609. }
  610. case ENUM_RESPONSE_DATA_KIND: // Service Provider's Enumeration Response
  611. {
  612. // Enum payload field
  613. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_ENUMPAYLOAD].hProperty,
  614. sizeof(rSPFrame.EnumResponseDataHeader.wEnumResponsePayload), &rSPFrame.EnumResponseDataHeader.wEnumResponsePayload, 0, 1, 0);
  615. // Enum Key field
  616. DWORD dwEnumKey = rSPFrame.EnumResponseDataHeader.wEnumResponsePayload & ~ENUM_RTT_MASK;
  617. AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_ENUMRESPKEY].hProperty,
  618. sizeof(rSPFrame.EnumResponseDataHeader.wEnumResponsePayload), &rSPFrame.EnumResponseDataHeader.wEnumResponsePayload,
  619. sizeof(dwEnumKey), &dwEnumKey,
  620. 0, 2, 0);
  621. // RTT index field
  622. BYTE byRTTIndex = rSPFrame.EnumDataHeader.wEnumPayload & ENUM_RTT_MASK;
  623. AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_RTTINDEX].hProperty,
  624. sizeof(rSPFrame.EnumResponseDataHeader.wEnumResponsePayload), &rSPFrame.EnumResponseDataHeader.wEnumResponsePayload,
  625. sizeof(byRTTIndex), &byRTTIndex,
  626. 0, 2, 0);
  627. break;
  628. }
  629. case PROXIED_ENUM_DATA_KIND: // Service Provider's Proxied Enumeration Query
  630. {
  631. // Return Address Size field
  632. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRSIZE].hProperty,
  633. sizeof(rSPFrame.ProxiedEnumDataHeader.ReturnAddress), &rSPFrame.ProxiedEnumDataHeader.ReturnAddress, 0, 1, 0);
  634. // Enum Key field
  635. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_ENUMKEY].hProperty,
  636. sizeof(rSPFrame.ProxiedEnumDataHeader.wEnumKey), &rSPFrame.ProxiedEnumDataHeader.wEnumKey, 0, 1, 0);
  637. // Return Address Socket Address Family field
  638. //
  639. // Technically we don't know that this is not the smaller non-IPv6 capable version of
  640. // this message. However, since PROXIED_ENUM_DATA_KIND is only ever sent locally, it
  641. // won't even show up in the parser, so it doesn't really matter.
  642. AttachPropertyInstance(i_hFrame,
  643. g_arr_SPProperties[SP_RETADDRFAMILY].hProperty,
  644. sizeof(rSPFrame.ProxiedEnumDataHeader.ReturnAddress.AddressGeneric.sa_family),
  645. &rSPFrame.ProxiedEnumDataHeader.ReturnAddress.AddressGeneric.sa_family,
  646. 0, 1, 0);
  647. switch ( rSPFrame.ProxiedEnumDataHeader.ReturnAddress.AddressGeneric.sa_family )
  648. {
  649. case AF_IPX:
  650. {
  651. SOCKADDR_IPX& rIPXAddress = rSPFrame.ProxiedEnumDataHeader.ReturnAddress.AddressIPX;
  652. // Return Address field (IPX Network Number + Node Number)
  653. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDR_IPX].hProperty,
  654. sizeof(rIPXAddress.sa_netnum) + sizeof(rIPXAddress.sa_nodenum), &rIPXAddress.sa_netnum, 0, 1, 0);
  655. // Return Address Socket Address IPX Socket Number field
  656. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRSOCKET_IPX].hProperty,
  657. sizeof(rIPXAddress.sa_socket), &rIPXAddress.sa_socket, 0, 1, 0);
  658. break;
  659. }
  660. case AF_INET:
  661. {
  662. SOCKADDR_IN& rIPAddress = rSPFrame.ProxiedEnumDataHeader.ReturnAddress.AddressIPv4;
  663. // Return Address field (IP Address)
  664. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDR_IP].hProperty,
  665. sizeof(rIPAddress.sin_addr), &rIPAddress.sin_addr, 0, 1, 0);
  666. // Return Address Port field
  667. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRPORT_IP].hProperty,
  668. sizeof(rIPAddress.sin_port), &rIPAddress.sin_port, 0, 1, 0);
  669. break;
  670. }
  671. case AF_INET6:
  672. {
  673. SOCKADDR_IN6& rIPv6Address = rSPFrame.ProxiedEnumDataHeader.ReturnAddress.AddressIPv6;
  674. // Return Address field (IP Address)
  675. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDR_IPV6].hProperty,
  676. sizeof(rIPv6Address.sin6_addr), &rIPv6Address.sin6_addr, 0, 1, 0);
  677. // Return Address Port field
  678. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRPORT_IP].hProperty,
  679. sizeof(rIPv6Address.sin6_port), &rIPv6Address.sin6_port, 0, 1, 0);
  680. break;
  681. }
  682. default:
  683. {
  684. // TODO: DPF(0, "Unknown socket type!");
  685. break;
  686. }
  687. }
  688. break;
  689. }
  690. }
  691. size_t sztSPHeaderSize = SPHeaderSize(i_upbSPFrame);
  692. if ( i_dwBytesLeft > sztSPHeaderSize )
  693. {
  694. size_t sztUserDataSize = i_dwBytesLeft - sztSPHeaderSize;
  695. // User data
  696. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_USERDATA].hProperty,
  697. sztUserDataSize, i_upbSPFrame + sztSPHeaderSize, 0, 1, 0);
  698. }
  699. return NULL;
  700. } // SPAttachProperties
  701. // DESCRIPTION: Formats the data that is displayed in the details pane of the Network Monitor UI.
  702. //
  703. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  704. // i_pbMacFrame - Pointer to the first byte of a frame.
  705. // i_pbCoreFrame - Pointer to the beginning of the protocol data in a frame.
  706. // i_dwPropertyInsts - Number of PROPERTYINST structures provided by lpPropInst.
  707. // i_pPropInst - Pointer to an array of PROPERTYINST structures.
  708. //
  709. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized data in a frame,
  710. // or NULL if the recognized data is the last piece of data in a frame. If the function is unsuccessful, the return value
  711. // is the initial value of i_pbSPFrame.
  712. //
  713. DPLAYPARSER_API DWORD BHAPI SPFormatProperties( HFRAME i_hFrame,
  714. ULPBYTE i_upbMacFrame,
  715. ULPBYTE i_upbSPFrame,
  716. DWORD i_dwPropertyInsts,
  717. LPPROPERTYINST i_pPropInst )
  718. {
  719. // Loop through the property instances...
  720. while( i_dwPropertyInsts-- > 0)
  721. {
  722. // ...and call the formatter for each
  723. reinterpret_cast<FORMAT>(i_pPropInst->lpPropertyInfo->InstanceData)(i_pPropInst);
  724. ++i_pPropInst;
  725. }
  726. // TODO: MAKE SURE THIS SHOULD NOT BE TRUE
  727. return NMERR_SUCCESS;
  728. } // SPFormatProperties
  729. // DESCRIPTION: Notifies Network Monitor that DPlay v8 Transport protocol parser exists.
  730. //
  731. // ARGUMENTS: NONE
  732. //
  733. // RETURNS: TRUE - success, FALSE - failure
  734. //
  735. bool CreateSPProtocol( void )
  736. {
  737. // The entry points to the export functions that Network Monitor uses to operate the parser
  738. ENTRYPOINTS SPEntryPoints =
  739. {
  740. // SPParser Entry Points
  741. SPRegister,
  742. SPDeregister,
  743. SPRecognizeFrame,
  744. SPAttachProperties,
  745. SPFormatProperties
  746. };
  747. // The first active instance of this parser needs to register with the kernel
  748. g_hSPProtocol = CreateProtocol("DPLAYSP", &SPEntryPoints, ENTRYPOINTS_SIZE);
  749. return (g_hSPProtocol ? TRUE : FALSE);
  750. } // CreateSPProtocol
  751. // DESCRIPTION: Removes the DPlay v8 Transport protocol parser from the Network Monitor's database of parsers
  752. //
  753. // ARGUMENTS: NONE
  754. //
  755. // RETURNS: NOTHING
  756. //
  757. void DestroySPProtocol( void )
  758. {
  759. DestroyProtocol(g_hSPProtocol);
  760. } // DestroySPProtocol