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.

910 lines
29 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 <tchar.h>
  19. //=====================//
  20. // Proprietary headers //
  21. //=====================//
  22. #include "dpaddr.h" // DPNA_DEFAULT_PORT definition
  23. // Prototypes
  24. #include "SPParser.hpp"
  25. namespace DPlaySP
  26. {
  27. // SP protocol header
  28. #include "MessageStructures.h"
  29. } // DPlaySP namespace
  30. namespace
  31. {
  32. HPROTOCOL g_hSPProtocol;
  33. //=============================//
  34. // Return Address Family field //-----------------------------------------------------------------------------------
  35. //=============================//
  36. LABELED_BYTE arr_RetAddrFamilyByteLabels[] = { { AF_IPX, "IPX protocol" },
  37. { AF_INET, "IP protocol" } };
  38. SET LabeledRetAddrFamilyByteSet = { sizeof(arr_RetAddrFamilyByteLabels) / sizeof(LABELED_BYTE), arr_RetAddrFamilyByteLabels };
  39. //================//
  40. // Data Tag field //------------------------------------------------------------------------------------------------
  41. //================//
  42. LABELED_BYTE arr_CommandByteLabels[] = { { ESCAPED_USER_DATA_KIND, "DPlay v8 Transport data follows" },
  43. { ENUM_DATA_KIND, "Enumeration Query" },
  44. { ENUM_RESPONSE_DATA_KIND, "Response to Enumeration Query" },
  45. { PROXIED_ENUM_DATA_KIND, "Proxied Enumeration Query" } };
  46. SET LabeledCommandByteSet = { sizeof(arr_CommandByteLabels) / sizeof(LABELED_BYTE), arr_CommandByteLabels };
  47. ////////////////////////////////
  48. // Custom Property Formatters //=====================================================================================
  49. ////////////////////////////////
  50. // DESCRIPTION: Custom description formatter for the Service Provider packet summary
  51. //
  52. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  53. //
  54. // RETURNS: NOTHING
  55. //
  56. VOID WINAPIV FormatPropertyInstance_SPSummary( LPPROPERTYINST io_pProperyInstance )
  57. {
  58. using namespace DPlaySP;
  59. // Check what SP frame we are dealing with
  60. PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(io_pProperyInstance->lpData);
  61. //
  62. switch ( rSPFrame.GenericHeader.bSPCommandByte )
  63. {
  64. case ENUM_DATA_KIND: // Service Provider Query
  65. {
  66. strcpy(io_pProperyInstance->szPropertyText, "Enumeration Request");
  67. break;
  68. }
  69. case ENUM_RESPONSE_DATA_KIND: // Service Provider Response
  70. {
  71. strcpy(io_pProperyInstance->szPropertyText, "Enumeration Response");
  72. break;
  73. }
  74. case PROXIED_ENUM_DATA_KIND: // Service Provider Proxied Query
  75. {
  76. strcpy(io_pProperyInstance->szPropertyText, "Proxied Enumeration Request");
  77. break;
  78. }
  79. case ESCAPED_USER_DATA_KIND: // DPlay v8 Transport protocol frame follows
  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. // User Data (SP_USERDATA)
  249. {
  250. 0, // handle placeholder (MBZ)
  251. 0, // reserved (MBZ)
  252. "User Data", // label
  253. "User Data", // status-bar comment
  254. PROP_TYPE_RAW_DATA, // data type
  255. PROP_QUAL_NONE, // data type qualifier.
  256. NULL, // labeled bit set
  257. 64, // description's maximum length
  258. FormatPropertyInstance // generic formatter
  259. }
  260. };
  261. enum
  262. {
  263. nNUM_OF_SP_PROPS = sizeof(g_arr_SPProperties) / sizeof(PROPERTYINFO)
  264. };
  265. // Properties' indices
  266. enum
  267. {
  268. SP_SUMMARY = 0,
  269. SP_LEADZERO,
  270. SP_COMMAND,
  271. SP_ENUMPAYLOAD,
  272. SP_ENUMKEY,
  273. SP_ENUMRESPKEY,
  274. SP_RTTINDEX,
  275. SP_RETADDRSIZE,
  276. SP_RETADDRFAMILY,
  277. SP_RETADDR_IPX,
  278. SP_RETADDRSOCKET_IPX,
  279. SP_RETADDR_IP,
  280. SP_RETADDRPORT_IP,
  281. SP_USERDATA
  282. };
  283. // Platform independent memory accessor of big endian words
  284. inline WORD ReadBigEndianWord( BYTE* i_pbData )
  285. {
  286. return (*i_pbData << 8) | *(i_pbData+1);
  287. }
  288. // DESCRIPTION: DPlay packet validation predicate.
  289. //
  290. // ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
  291. // i_hPrevProtocol - Handle of the previous protocol.
  292. // i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
  293. // the data that the other parsers recognize.
  294. //
  295. // RETURNS: DPlay packet = TRUE; NOT a DPlay packet = FALSE
  296. //
  297. bool IsDPlayPacket( HFRAME i_hFrame, HPROTOCOL i_hPrevProtocol, LPBYTE i_pbMacFrame )
  298. {
  299. LPPROTOCOLINFO pPrevProtocolInfo = GetProtocolInfo(i_hPrevProtocol);
  300. DWORD dwPrevProtocolOffset = GetProtocolStartOffsetHandle(i_hFrame, i_hPrevProtocol);
  301. WORD wSrcPort, wDstPort;
  302. if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "UDP", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  303. {
  304. // Extracting the source and destination ports of the packet from its UDP header
  305. wSrcPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset);
  306. wDstPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 2);
  307. }
  308. else if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "IPX", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  309. {
  310. // Extracting the source and destination ports of the packet from its IPX header
  311. wSrcPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 16); // source address socket
  312. wDstPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 28); // destination address socket
  313. }
  314. else
  315. {
  316. // Should never happen!
  317. return false;
  318. }
  319. //===========//
  320. // Constants //
  321. //===========//
  322. //
  323. static bool bTriedRetrievingUserPorts = false;
  324. static bool bRetrievedUserPorts = false;
  325. static DWORD dwMinUserPort, dwMaxUserPort;
  326. // Retrieval from the registry is attempted only once
  327. if ( !bTriedRetrievingUserPorts )
  328. {
  329. bTriedRetrievingUserPorts = true;
  330. HKEY hKey = NULL;
  331. if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\DirectPlay\\Parsers"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  332. {
  333. DWORD dwType = NULL;
  334. DWORD dwCount = sizeof(DWORD);
  335. if (RegQueryValueEx(hKey, _T("MinUserPort"), NULL, &dwType, (LPBYTE)&dwMinUserPort, &dwCount) == ERROR_SUCCESS &&
  336. RegQueryValueEx(hKey, _T("MaxUserPort"), NULL, &dwType, (LPBYTE)&dwMaxUserPort, &dwCount) == ERROR_SUCCESS )
  337. {
  338. bRetrievedUserPorts = true;
  339. }
  340. RegCloseKey(hKey);
  341. }
  342. }
  343. if ( bRetrievedUserPorts &&
  344. ((wSrcPort >= dwMinUserPort) && (wSrcPort <= dwMaxUserPort)) &&
  345. ((wDstPort >= dwMinUserPort) && (wDstPort <= dwMaxUserPort)) )
  346. {
  347. // Is a valid DPlay packet
  348. return true;
  349. }
  350. // 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)
  351. WORD wPort = wSrcPort;
  352. for ( int nPorts = 0; nPorts < 2; ++nPorts, wPort = wDstPort )
  353. {
  354. if (
  355. (
  356. !bRetrievedUserPorts ||
  357. (wPort < dwMinUserPort) ||
  358. (wPort > dwMaxUserPort)
  359. )
  360. &&
  361. (
  362. (wPort < BASE_DPLAY8_PORT) ||
  363. (wPort > MAX_DPLAY8_PORT)
  364. )
  365. &&
  366. (
  367. wPort != DPNA_DPNSVR_PORT
  368. )
  369. )
  370. {
  371. // Not a valid DPlay packet
  372. return false;
  373. }
  374. }
  375. // Is a valid DPlay packet
  376. return true;
  377. } // IsDPlayPacket
  378. } // anonymous namespace
  379. // DESCRIPTION: Creates and fills-in a properties database for the protocol.
  380. // Network Monitor uses this database to determine which properties the protocol supports.
  381. //
  382. // ARGUMENTS: i_hSPProtocol - The handle of the protocol provided by the Network Monitor.
  383. //
  384. // RETURNS: NOTHING
  385. //
  386. DPLAYPARSER_API VOID BHAPI SPRegister( HPROTOCOL i_hSPProtocol )
  387. {
  388. CreatePropertyDatabase(i_hSPProtocol, nNUM_OF_SP_PROPS);
  389. // Add the properties to the database
  390. for( int nProp=0; nProp < nNUM_OF_SP_PROPS; ++nProp )
  391. {
  392. AddProperty(i_hSPProtocol, &g_arr_SPProperties[nProp]);
  393. }
  394. } // SPRegister
  395. // DESCRIPTION: Frees the resources used to create the protocol property database.
  396. //
  397. // ARGUMENTS: i_hSPProtocol - The handle of the protocol provided by the Network Monitor.
  398. //
  399. // RETURNS: NOTHING
  400. //
  401. DPLAYPARSER_API VOID WINAPI SPDeregister( HPROTOCOL i_hProtocol )
  402. {
  403. DestroyPropertyDatabase(i_hProtocol);
  404. } // SPDeregister
  405. namespace
  406. {
  407. // DESCRIPTION: Parses the SP frame to find its size (in bytes) NOT including the user data
  408. //
  409. // ARGUMENTS: i_pbSPFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  410. // in the middle of a frame because a previous parser has claimed data before this parser.
  411. //
  412. // RETURNS: Size of the specified SP frame (in bytes)
  413. //
  414. int SPHeaderSize( LPBYTE i_pbSPFrame )
  415. {
  416. using namespace DPlaySP;
  417. // Check what SP frame we are dealing with
  418. PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_pbSPFrame);
  419. //
  420. switch ( rSPFrame.GenericHeader.bSPCommandByte )
  421. {
  422. case ENUM_DATA_KIND: // Service Provider Query
  423. {
  424. return sizeof(rSPFrame.EnumDataHeader);
  425. }
  426. case ENUM_RESPONSE_DATA_KIND: // Service Provider Response
  427. {
  428. return sizeof(rSPFrame.EnumResponseDataHeader);
  429. }
  430. case PROXIED_ENUM_DATA_KIND: // Service Provider Proxied Query
  431. {
  432. return sizeof(rSPFrame.ProxiedEnumDataHeader);
  433. }
  434. case ESCAPED_USER_DATA_KIND: // user data starting with zero
  435. {
  436. return sizeof(rSPFrame.EscapedUserDataHeader);
  437. }
  438. default: // user data starting with a nonzero byte
  439. {
  440. return 0; // no header
  441. }
  442. }
  443. } // SPHeaderSize
  444. } // Anonymous namespace
  445. // DESCRIPTION: Indicates whether a piece of data is recognized as the protocol that the parser detects.
  446. //
  447. // ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
  448. // i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
  449. // the data that the other parsers recognize.
  450. // i_pbSPFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  451. // in the middle of a frame because a previous parser has claimed data before this parser.
  452. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  453. // when the parser must identify the first protocol in the frame. Can be one of the following:
  454. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  455. // i_dwBytesLeft - The remaining number of bytes from a location in the frame to the end of the frame.
  456. // i_hPrevProtocol - Handle of the previous protocol.
  457. // i_dwPrevProtOffset - Offset of the previous protocol (from the beginning of the frame).
  458. // o_pdwProtocolStatus - Protocol status indicator. Must be one of the following: PROTOCOL_STATUS_RECOGNIZED,
  459. // PROTOCOL_STATUS_NOT_RECOGNIZED, PROTOCOL_STATUS_CLAIMED, PROTOCOL_STATUS_NEXT_PROTOCOL.
  460. // o_phNextProtocol - Placeholder for the handle of the next protocol. This parameter is set when the parser identifies
  461. // the protocol that follows its own protocol.
  462. // io_pdwptrInstData - On input, a pointer to the instance data from the previous protocol.
  463. // On output, a pointer to the instance data for the current protocol.
  464. //
  465. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized parser data.
  466. // If the parser claims all the remaining data, the return value is NULL. If the function is unsuccessful, the return
  467. // value is the initial value of the i_pbSPFrame parameter.
  468. //
  469. DPLAYPARSER_API LPBYTE BHAPI SPRecognizeFrame( HFRAME i_hFrame,
  470. ULPBYTE i_upbMacFrame,
  471. ULPBYTE i_upbSPFrame,
  472. DWORD i_dwMacType,
  473. DWORD i_dwBytesLeft,
  474. HPROTOCOL i_hPrevProtocol,
  475. DWORD i_dwPrevProtOffset,
  476. LPDWORD o_pdwProtocolStatus,
  477. LPHPROTOCOL o_phNextProtocol,
  478. PDWORD_PTR io_pdwptrInstData )
  479. {
  480. using namespace DPlaySP;
  481. // Validate the amount of unclaimed data
  482. enum
  483. {
  484. nMIN_SPHeaderSize = sizeof(PREPEND_BUFFER::_GENERIC_HEADER)
  485. };
  486. // Validate the packet as DPlay SP type
  487. if ( (i_dwBytesLeft < nMIN_SPHeaderSize) ||
  488. !IsDPlayPacket(i_hFrame, i_hPrevProtocol, i_upbMacFrame) )
  489. {
  490. // Assume the unclaimed data is not recognizable
  491. *o_pdwProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
  492. return i_upbSPFrame;
  493. }
  494. //==========================//
  495. // Get the DPlay frame size //
  496. //==========================//
  497. LPPROTOCOLINFO pPrevProtocolInfo = GetProtocolInfo(i_hPrevProtocol);
  498. WORD wDPlayFrameSize = 0;
  499. if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "UDP", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  500. {
  501. // Extracting the UDP frame size
  502. WORD wUDPFrameSize = ReadBigEndianWord(i_upbMacFrame + i_dwPrevProtOffset + 4);
  503. enum { nUDP_HEADER_SIZE = 8 };
  504. wDPlayFrameSize = wUDPFrameSize - nUDP_HEADER_SIZE;
  505. }
  506. else if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "IPX", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
  507. {
  508. // Extracting the IPX frame size
  509. WORD wIPXFrameSize = ReadBigEndianWord(i_upbMacFrame + i_dwPrevProtOffset + 2); // source address socket
  510. enum { nIPX_HEADER_SIZE = 30 };
  511. wDPlayFrameSize = wIPXFrameSize - nIPX_HEADER_SIZE;
  512. }
  513. else
  514. {
  515. ; // TODO: ASSERT HERE
  516. }
  517. // Pass along the size of the Transport frame
  518. DWORD_PTR dwptrTransportFrameSize = wDPlayFrameSize - SPHeaderSize(i_upbSPFrame);
  519. *io_pdwptrInstData = dwptrTransportFrameSize;
  520. PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_upbSPFrame);
  521. if ( rSPFrame.GenericHeader.bSPLeadByte == SP_HEADER_LEAD_BYTE ) // SP packet
  522. {
  523. *o_pdwProtocolStatus = PROTOCOL_STATUS_RECOGNIZED;
  524. *o_phNextProtocol = NULL;
  525. if ( rSPFrame.GenericHeader.bSPCommandByte == ESCAPED_USER_DATA_KIND ) // user data starting with zero (non-DPlay v8 Transport packet)
  526. {
  527. *o_pdwProtocolStatus = PROTOCOL_STATUS_RECOGNIZED;
  528. return i_upbSPFrame + sizeof(PREPEND_BUFFER::_ESCAPED_USER_DATA_HEADER);
  529. }
  530. }
  531. else // user data (DPlay v8 Transport packet)
  532. {
  533. // Notify NetMon about the handoff protocol
  534. *o_pdwProtocolStatus = PROTOCOL_STATUS_NEXT_PROTOCOL;
  535. *o_phNextProtocol = GetProtocolFromName("DPLAYTRANSPORT");
  536. return i_upbSPFrame;
  537. }
  538. // Claim the rest of the data
  539. return NULL;
  540. } // SPRecognizeFrame
  541. // DESCRIPTION: Maps the properties that exist in a piece of recognized data to specific locations.
  542. //
  543. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  544. // i_pbMacFram - Pointer to the first byte in the frame.
  545. // i_pbSPFrame - Pointer to the start of the recognized data.
  546. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  547. // when the parser must identify the first protocol in the frame. Can be one of the following:
  548. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  549. // i_dwBytesLeft - The remaining number of bytes in a frame (starting from the beginning of the recognized data).
  550. // i_hPrevProtocol - Handle of the previous protocol.
  551. // i_dwPrevProtOffset - Offset of the previous protocol (starting from the beginning of the frame).
  552. // i_dwptrInstData - Pointer to the instance data that the previous protocol provides.
  553. //
  554. // RETURNS: Must return NULL
  555. //
  556. DPLAYPARSER_API LPBYTE BHAPI SPAttachProperties( HFRAME i_hFrame,
  557. ULPBYTE i_upbMacFrame,
  558. ULPBYTE i_upbSPFrame,
  559. DWORD i_dwMacType,
  560. DWORD i_dwBytesLeft,
  561. HPROTOCOL i_hPrevProtocol,
  562. DWORD i_dwPrevProtOffset,
  563. DWORD_PTR i_dwptrInstData )
  564. {
  565. using namespace DPlaySP;
  566. //===================//
  567. // Attach Properties //
  568. //===================//
  569. // Summary line
  570. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_SUMMARY].hProperty,
  571. i_dwBytesLeft, i_upbSPFrame, 0, 0, 0);
  572. // Protection against NetMon
  573. if ( *i_upbSPFrame )
  574. {
  575. return NULL;
  576. }
  577. // Check what SP frame we are dealing with
  578. PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_upbSPFrame);
  579. // Leading Zero tag field
  580. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_LEADZERO].hProperty,
  581. sizeof(rSPFrame.GenericHeader.bSPLeadByte), &rSPFrame.GenericHeader.bSPLeadByte, 0, 1, 0);
  582. // Command field
  583. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_COMMAND].hProperty,
  584. sizeof(rSPFrame.GenericHeader.bSPCommandByte), &rSPFrame.GenericHeader.bSPCommandByte, 0, 1, 0);
  585. switch ( rSPFrame.GenericHeader.bSPCommandByte )
  586. {
  587. case ESCAPED_USER_DATA_KIND: // user data starting with zero
  588. {
  589. break;
  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. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRFAMILY].hProperty,
  639. sizeof(rSPFrame.ProxiedEnumDataHeader.ReturnAddress.sa_family), &rSPFrame.ProxiedEnumDataHeader.ReturnAddress.sa_family, 0, 1, 0);
  640. switch ( rSPFrame.ProxiedEnumDataHeader.ReturnAddress.sa_family )
  641. {
  642. case AF_IPX:
  643. {
  644. SOCKADDR_IPX& rIPXAddress = *reinterpret_cast<SOCKADDR_IPX*>(&rSPFrame.ProxiedEnumDataHeader.ReturnAddress);
  645. // Return Address field (IPX Network Number + Node Number)
  646. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDR_IPX].hProperty,
  647. sizeof(rIPXAddress.sa_netnum) + sizeof(rIPXAddress.sa_nodenum), &rIPXAddress.sa_netnum, 0, 1, 0);
  648. // Return Address Socket Address IPX Socket Number field
  649. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRSOCKET_IPX].hProperty,
  650. sizeof(rIPXAddress.sa_socket), &rIPXAddress.sa_socket, 0, 1, 0);
  651. break;
  652. }
  653. case AF_INET:
  654. {
  655. SOCKADDR_IN& rIPAddress = *reinterpret_cast<SOCKADDR_IN*>(&rSPFrame.ProxiedEnumDataHeader.ReturnAddress);
  656. // Return Address field (IP Address)
  657. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDR_IP].hProperty,
  658. sizeof(rIPAddress.sin_addr), &rIPAddress.sin_addr, 0, 1, 0);
  659. // Return Address Port field
  660. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRPORT_IP].hProperty,
  661. sizeof(rIPAddress.sin_port), &rIPAddress.sin_port, 0, 1, 0);
  662. break;
  663. }
  664. default:
  665. {
  666. // TODO: DPF(0, "Unknown socket type!");
  667. break;
  668. }
  669. }
  670. break;
  671. }
  672. }
  673. size_t sztSPHeaderSize = SPHeaderSize(i_upbSPFrame);
  674. if ( i_dwBytesLeft > sztSPHeaderSize )
  675. {
  676. size_t sztUserDataSize = i_dwBytesLeft - sztSPHeaderSize;
  677. // User data
  678. AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_USERDATA].hProperty,
  679. sztUserDataSize, i_upbSPFrame + sztSPHeaderSize, 0, 1, 0);
  680. }
  681. return NULL;
  682. } // SPAttachProperties
  683. // DESCRIPTION: Formats the data that is displayed in the details pane of the Network Monitor UI.
  684. //
  685. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  686. // i_pbMacFrame - Pointer to the first byte of a frame.
  687. // i_pbCoreFrame - Pointer to the beginning of the protocol data in a frame.
  688. // i_dwPropertyInsts - Number of PROPERTYINST structures provided by lpPropInst.
  689. // i_pPropInst - Pointer to an array of PROPERTYINST structures.
  690. //
  691. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized data in a frame,
  692. // or NULL if the recognized data is the last piece of data in a frame. If the function is unsuccessful, the return value
  693. // is the initial value of i_pbSPFrame.
  694. //
  695. DPLAYPARSER_API DWORD BHAPI SPFormatProperties( HFRAME i_hFrame,
  696. ULPBYTE i_upbMacFrame,
  697. ULPBYTE i_upbSPFrame,
  698. DWORD i_dwPropertyInsts,
  699. LPPROPERTYINST i_pPropInst )
  700. {
  701. // Loop through the property instances...
  702. while( i_dwPropertyInsts-- > 0)
  703. {
  704. // ...and call the formatter for each
  705. reinterpret_cast<FORMAT>(i_pPropInst->lpPropertyInfo->InstanceData)(i_pPropInst);
  706. ++i_pPropInst;
  707. }
  708. // TODO: MAKE SURE THIS SHOULD NOT BE TRUE
  709. return NMERR_SUCCESS;
  710. } // SPFormatProperties
  711. // DESCRIPTION: Notifies Network Monitor that DPlay v8 Transport protocol parser exists.
  712. //
  713. // ARGUMENTS: NONE
  714. //
  715. // RETURNS: TRUE - success, FALSE - failure
  716. //
  717. bool CreateSPProtocol( void )
  718. {
  719. // The entry points to the export functions that Network Monitor uses to operate the parser
  720. ENTRYPOINTS SPEntryPoints =
  721. {
  722. // SPParser Entry Points
  723. SPRegister,
  724. SPDeregister,
  725. SPRecognizeFrame,
  726. SPAttachProperties,
  727. SPFormatProperties
  728. };
  729. // The first active instance of this parser needs to register with the kernel
  730. g_hSPProtocol = CreateProtocol("DPLAYSP", &SPEntryPoints, ENTRYPOINTS_SIZE);
  731. return (g_hSPProtocol ? TRUE : FALSE);
  732. } // CreateSPProtocol
  733. // DESCRIPTION: Removes the DPlay v8 Transport protocol parser from the Network Monitor's database of parsers
  734. //
  735. // ARGUMENTS: NONE
  736. //
  737. // RETURNS: NOTHING
  738. //
  739. void DestroySPProtocol( void )
  740. {
  741. DestroyProtocol(g_hSPProtocol);
  742. } // DestroySPProtocol