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.

690 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. D:\nt\private\ntos\tdi\rawwan\core\info.c
  5. Abstract:
  6. Routines for handling query/set information requests.
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. arvindm 06-09-97 Created
  11. Notes:
  12. --*/
  13. #include <precomp.h>
  14. #define _FILENUMBER 'OFNI'
  15. //
  16. // Kludgy way to ensure we have enough space for a transport
  17. // address in the following INFO BUF structure.
  18. //
  19. #define MAX_RWAN_TDI_INFO_LENGTH 200
  20. typedef union _RWAN_TDI_INFO_BUF
  21. {
  22. TDI_CONNECTION_INFO ConnInfo;
  23. TDI_ADDRESS_INFO AddrInfo;
  24. TDI_PROVIDER_INFO ProviderInfo;
  25. TDI_PROVIDER_STATISTICS ProviderStats;
  26. UCHAR Space[MAX_RWAN_TDI_INFO_LENGTH];
  27. } RWAN_TDI_INFO_BUF, *PRWAN_TDI_INFO_BUF;
  28. TDI_STATUS
  29. RWanTdiQueryInformation(
  30. IN PTDI_REQUEST pTdiRequest,
  31. IN UINT QueryType,
  32. IN PNDIS_BUFFER pNdisBuffer,
  33. IN PUINT pBufferSize,
  34. IN UINT IsConnection
  35. )
  36. /*++
  37. Routine Description:
  38. This is the TDI entry point to handle a QueryInformation TDI request.
  39. Arguments:
  40. pTdiRequest - Pointer to the TDI Request
  41. QueryType - Information being queried for
  42. pNdisBuffer - Start of list of buffers containing query data
  43. pBufferSize - Total space in above list
  44. IsConnection - Is this query on a connection endpoint?
  45. Return Value:
  46. TDI_STATUS: TDI_SUCCESS if the query was processed
  47. successfully, TDI_STATUS_XXX for any error.
  48. --*/
  49. {
  50. TDI_STATUS TdiStatus;
  51. RWAN_TDI_INFO_BUF InfoBuf;
  52. PVOID InfoPtr;
  53. UINT InfoSize;
  54. UINT Offset;
  55. UINT Size;
  56. UINT BytesCopied;
  57. PRWAN_TDI_PROTOCOL pProtocol;
  58. PRWAN_TDI_ADDRESS pAddrObject;
  59. PRWAN_TDI_CONNECTION pConnObject;
  60. RWAN_CONN_ID ConnId;
  61. TdiStatus = TDI_SUCCESS;
  62. InfoPtr = NULL;
  63. switch (QueryType)
  64. {
  65. case TDI_QUERY_BROADCAST_ADDRESS:
  66. TdiStatus = TDI_INVALID_QUERY;
  67. break;
  68. case TDI_QUERY_PROVIDER_INFO:
  69. pProtocol = pTdiRequest->Handle.ControlChannel;
  70. RWAN_STRUCT_ASSERT(pProtocol, ntp);
  71. InfoBuf.ProviderInfo = pProtocol->ProviderInfo;
  72. InfoSize = sizeof(TDI_PROVIDER_INFO);
  73. InfoPtr = &InfoBuf.ProviderInfo;
  74. break;
  75. case TDI_QUERY_ADDRESS_INFO:
  76. if (IsConnection)
  77. {
  78. ConnId = (RWAN_CONN_ID) PtrToUlong(pTdiRequest->Handle.ConnectionContext);
  79. RWAN_ACQUIRE_CONN_TABLE_LOCK();
  80. pConnObject = RWanGetConnFromId(ConnId);
  81. RWAN_RELEASE_CONN_TABLE_LOCK();
  82. if (pConnObject == NULL_PRWAN_TDI_CONNECTION)
  83. {
  84. TdiStatus = TDI_INVALID_CONNECTION;
  85. break;
  86. }
  87. pAddrObject = pConnObject->pAddrObject;
  88. }
  89. else
  90. {
  91. pAddrObject = (PRWAN_TDI_ADDRESS)pTdiRequest->Handle.AddressHandle;
  92. }
  93. if (pAddrObject == NULL_PRWAN_TDI_ADDRESS)
  94. {
  95. TdiStatus = TDI_INVALID_CONNECTION;
  96. break;
  97. }
  98. RWAN_STRUCT_ASSERT(pAddrObject, nta);
  99. RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
  100. RWAN_ASSERT(pAddrObject->AddressLength <=
  101. (sizeof(RWAN_TDI_INFO_BUF) - sizeof(TDI_ADDRESS_INFO)));
  102. InfoSize = sizeof(TDI_ADDRESS_INFO) - sizeof(TRANSPORT_ADDRESS) +
  103. pAddrObject->AddressLength;
  104. InfoBuf.AddrInfo.ActivityCount = 1; // same as TCP
  105. InfoBuf.AddrInfo.Address.TAAddressCount = 1;
  106. InfoBuf.AddrInfo.Address.Address[0].AddressLength = pAddrObject->AddressLength;
  107. InfoBuf.AddrInfo.Address.Address[0].AddressType = pAddrObject->AddressType;
  108. RWAN_COPY_MEM(InfoBuf.AddrInfo.Address.Address[0].Address,
  109. pAddrObject->pAddress,
  110. pAddrObject->AddressLength);
  111. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  112. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  113. ("RWanTdiQueryInfo: IsConn %d, Addr dump:\n", IsConnection));
  114. RWANDEBUGPDUMP(DL_LOUD, DC_DISPATCH, pAddrObject->pAddress, pAddrObject->AddressLength);
  115. InfoPtr = &InfoBuf.AddrInfo;
  116. TdiStatus = TDI_SUCCESS;
  117. break;
  118. case TDI_QUERY_CONNECTION_INFO:
  119. TdiStatus = TDI_INVALID_QUERY;
  120. break;
  121. case TDI_QUERY_PROVIDER_STATISTICS:
  122. pProtocol = pTdiRequest->Handle.ControlChannel;
  123. RWAN_STRUCT_ASSERT(pProtocol, ntp);
  124. InfoBuf.ProviderStats = pProtocol->ProviderStats;
  125. InfoSize = sizeof(TDI_PROVIDER_STATISTICS);
  126. InfoPtr = &InfoBuf.ProviderStats;
  127. break;
  128. default:
  129. TdiStatus = TDI_INVALID_QUERY;
  130. break;
  131. }
  132. if (TdiStatus == TDI_SUCCESS)
  133. {
  134. RWAN_ASSERT(InfoPtr != NULL);
  135. Offset = 0;
  136. Size = *pBufferSize;
  137. (VOID)RWanCopyFlatToNdis(
  138. pNdisBuffer,
  139. InfoPtr,
  140. MIN(InfoSize, Size),
  141. &Offset,
  142. &BytesCopied
  143. );
  144. if (Size < InfoSize)
  145. {
  146. TdiStatus = TDI_BUFFER_OVERFLOW;
  147. }
  148. else
  149. {
  150. *pBufferSize = InfoSize;
  151. }
  152. }
  153. return (TdiStatus);
  154. }
  155. RWAN_STATUS
  156. RWanHandleGenericConnQryInfo(
  157. IN HANDLE ConnectionContext,
  158. IN PVOID pInputBuffer,
  159. IN ULONG InputBufferLength,
  160. OUT PVOID pOutputBuffer,
  161. IN OUT PVOID pOutputBufferLength
  162. )
  163. /*++
  164. Routine Description:
  165. Handle a generic QueryInformation command on a Connection Object.
  166. Arguments:
  167. AddrHandle - Pointer to our address object structure
  168. ConnectionContext - TDI Connection ID
  169. pInputBuffer - Query Info structure
  170. InputBufferLength - Length of the above
  171. pOutputBuffer - Output buffer
  172. pOutputBufferLength - Space available/bytes filled in.
  173. Return Value:
  174. RWAN_STATUS_SUCCESS if the command was processed successfully,
  175. RWAN_STATUS_XXX if not.
  176. --*/
  177. {
  178. PRWAN_TDI_CONNECTION pConnObject;
  179. RWAN_STATUS RWanStatus;
  180. PRWAN_QUERY_INFORMATION_EX pQueryInfo;
  181. RWanStatus = RWAN_STATUS_SUCCESS;
  182. do
  183. {
  184. if (InputBufferLength < sizeof(RWAN_QUERY_INFORMATION_EX) ||
  185. pOutputBuffer == NULL)
  186. {
  187. RWanStatus = RWAN_STATUS_RESOURCES;
  188. break;
  189. }
  190. RWAN_ACQUIRE_CONN_TABLE_LOCK();
  191. pConnObject = RWanGetConnFromId((RWAN_CONN_ID)PtrToUlong(ConnectionContext));
  192. RWAN_RELEASE_CONN_TABLE_LOCK();
  193. if (pConnObject == NULL)
  194. {
  195. RWanStatus = RWAN_STATUS_BAD_PARAMETER;
  196. break;
  197. }
  198. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  199. pQueryInfo = (PRWAN_QUERY_INFORMATION_EX)pInputBuffer;
  200. if (InputBufferLength < sizeof(RWAN_QUERY_INFORMATION_EX) + pQueryInfo->ContextLength - sizeof(UCHAR))
  201. {
  202. RWanStatus = RWAN_STATUS_RESOURCES;
  203. break;
  204. }
  205. switch (pQueryInfo->ObjectId)
  206. {
  207. case RWAN_OID_CONN_OBJECT_MAX_MSG_SIZE:
  208. if (*(PULONG)(ULONG_PTR)pOutputBufferLength < sizeof(ULONG))
  209. {
  210. RWanStatus = RWAN_STATUS_RESOURCES;
  211. break;
  212. }
  213. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  214. if (pConnObject->NdisConnection.pNdisVc)
  215. {
  216. *(PULONG)(ULONG_PTR)pOutputBuffer = pConnObject->NdisConnection.pNdisVc->MaxSendSize;
  217. *(PULONG)(ULONG_PTR)pOutputBufferLength = sizeof(ULONG);
  218. }
  219. else
  220. {
  221. RWanStatus = RWAN_STATUS_BAD_PARAMETER;
  222. }
  223. RWAN_RELEASE_CONN_LOCK(pConnObject);
  224. break;
  225. default:
  226. RWanStatus = RWAN_STATUS_BAD_PARAMETER;
  227. break;
  228. }
  229. break;
  230. }
  231. while (FALSE);
  232. RWANDEBUGP(DL_LOUD, DC_BIND,
  233. ("RWanHandleGenericConnQry: returning status %x\n", RWanStatus));
  234. return (RWanStatus);
  235. }
  236. RWAN_STATUS
  237. RWanHandleGenericAddrSetInfo(
  238. IN HANDLE AddrHandle,
  239. IN PVOID pInputBuffer,
  240. IN ULONG InputBufferLength
  241. )
  242. /*++
  243. Routine Description:
  244. Handle a non-media specific SetInformation command on an Address Object.
  245. Arguments:
  246. AddrHandle - Pointer to our address object structure
  247. pInputBuffer - Set Info structure
  248. InputBufferLength - Length of the above
  249. Return Value:
  250. RWAN_STATUS_SUCCESS if the command was processed successfully,
  251. RWAN_STATUS_XXX if not.
  252. --*/
  253. {
  254. PRWAN_TDI_ADDRESS pAddrObject;
  255. PRWAN_TDI_CONNECTION pConnObject;
  256. PRWAN_SET_INFORMATION_EX pSetInfo;
  257. RWAN_STATUS RWanStatus;
  258. ULONG Flags;
  259. RWanStatus = RWAN_STATUS_SUCCESS;
  260. pAddrObject = (PRWAN_TDI_ADDRESS)AddrHandle;
  261. do
  262. {
  263. if (pAddrObject == NULL)
  264. {
  265. RWanStatus = RWAN_STATUS_BAD_ADDRESS;
  266. break;
  267. }
  268. RWAN_STRUCT_ASSERT(pAddrObject, nta);
  269. if (InputBufferLength < sizeof(RWAN_SET_INFORMATION_EX))
  270. {
  271. RWanStatus = RWAN_STATUS_RESOURCES;
  272. break;
  273. }
  274. pSetInfo = (PRWAN_SET_INFORMATION_EX)pInputBuffer;
  275. if (InputBufferLength < sizeof(RWAN_SET_INFORMATION_EX) + pSetInfo->BufferSize - sizeof(UCHAR))
  276. {
  277. RWanStatus = RWAN_STATUS_RESOURCES;
  278. break;
  279. }
  280. switch (pSetInfo->ObjectId)
  281. {
  282. case RWAN_OID_ADDRESS_OBJECT_FLAGS:
  283. if (pSetInfo->BufferSize < sizeof(ULONG))
  284. {
  285. RWanStatus = RWAN_STATUS_RESOURCES;
  286. break;
  287. }
  288. Flags = *((PULONG)&pSetInfo->Buffer[0]);
  289. if (Flags & RWAN_AOFLAG_C_ROOT)
  290. {
  291. //
  292. // This Address Object is designated as the Root of
  293. // an outgoing Point to Multipoint connection.
  294. //
  295. RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
  296. RWAN_SET_BIT(pAddrObject->Flags, RWANF_AO_PMP_ROOT);
  297. if (pAddrObject->pRootConnObject != NULL)
  298. {
  299. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  300. RWanStatus = RWAN_STATUS_BAD_ADDRESS;
  301. break;
  302. }
  303. //
  304. // There should be a single Connection Object associated
  305. // with this Address Object. That should now be designated
  306. // the Root Connection Object.
  307. //
  308. RWAN_ASSERT(!RWAN_IS_LIST_EMPTY(&pAddrObject->IdleConnList));
  309. pConnObject = CONTAINING_RECORD(pAddrObject->IdleConnList.Flink, RWAN_TDI_CONNECTION, ConnLink);
  310. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  311. pAddrObject->pRootConnObject = pConnObject;
  312. RWAN_ACQUIRE_CONN_LOCK_DPC(pConnObject);
  313. RWAN_SET_BIT(pConnObject->Flags, RWANF_CO_ROOT);
  314. RWAN_RELEASE_CONN_LOCK_DPC(pConnObject);
  315. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  316. RWANDEBUGP(DL_LOUD, DC_ADDRESS,
  317. ("Marked PMP Root: AddrObj x%x, ConnObj x%x\n",
  318. pAddrObject, pConnObject));
  319. }
  320. break;
  321. default:
  322. RWanStatus = RWAN_STATUS_BAD_PARAMETER;
  323. break;
  324. }
  325. break;
  326. }
  327. while (FALSE);
  328. RWANDEBUGP(DL_VERY_LOUD, DC_DISPATCH,
  329. ("Generic Set Addr: AddrObj x%x, returning x%x\n", pAddrObject, RWanStatus));
  330. return (RWanStatus);
  331. }
  332. RWAN_STATUS
  333. RWanHandleMediaSpecificAddrSetInfo(
  334. IN HANDLE AddrHandle,
  335. IN PVOID pInputBuffer,
  336. IN ULONG InputBufferLength
  337. )
  338. /*++
  339. Routine Description:
  340. Handle a media specific SetInformation command on an Address Object.
  341. Arguments:
  342. AddrHandle - Pointer to our address object structure
  343. pInputBuffer - Set Info structure
  344. InputBufferLength - Length of the above
  345. Return Value:
  346. RWAN_STATUS_SUCCESS if the command was processed successfully,
  347. RWAN_STATUS_XXX if not.
  348. --*/
  349. {
  350. PRWAN_NDIS_AF_CHARS pAfChars;
  351. PRWAN_TDI_ADDRESS pAddrObject;
  352. RWAN_STATUS RWanStatus;
  353. ULONG Flags;
  354. RWanStatus = RWAN_STATUS_SUCCESS;
  355. pAddrObject = (PRWAN_TDI_ADDRESS)AddrHandle;
  356. do
  357. {
  358. if (pAddrObject == NULL)
  359. {
  360. RWanStatus = RWAN_STATUS_BAD_ADDRESS;
  361. break;
  362. }
  363. RWAN_STRUCT_ASSERT(pAddrObject, nta);
  364. pAfChars = &(pAddrObject->pProtocol->pAfInfo->AfChars);
  365. if (pAfChars->pAfSpSetAddrInformation != NULL)
  366. {
  367. RWanStatus = (*pAfChars->pAfSpSetAddrInformation)(
  368. pAddrObject->AfSpAddrContext,
  369. pInputBuffer,
  370. InputBufferLength
  371. );
  372. }
  373. else
  374. {
  375. RWanStatus = RWAN_STATUS_FAILURE;
  376. }
  377. break;
  378. }
  379. while (FALSE);
  380. return (RWanStatus);
  381. }
  382. RWAN_STATUS
  383. RWanHandleMediaSpecificConnQryInfo(
  384. IN HANDLE ConnectionContext,
  385. IN PVOID pInputBuffer,
  386. IN ULONG InputBufferLength,
  387. OUT PVOID pOutputBuffer,
  388. IN OUT PVOID pOutputBufferLength
  389. )
  390. /*++
  391. Routine Description:
  392. Handle a media specific QueryInformation command on a Connection Object.
  393. Arguments:
  394. AddrHandle - Pointer to our address object structure
  395. ConnectionContext - TDI Connection ID
  396. pInputBuffer - Query Info structure
  397. InputBufferLength - Length of the above
  398. pOutputBuffer - Output buffer
  399. pOutputBufferLength - Space available/bytes filled in.
  400. Return Value:
  401. RWAN_STATUS_SUCCESS if the command was processed successfully,
  402. RWAN_STATUS_XXX if not.
  403. --*/
  404. {
  405. PRWAN_NDIS_AF_CHARS pAfChars;
  406. PRWAN_TDI_CONNECTION pConnObject;
  407. RWAN_STATUS RWanStatus;
  408. ULONG Flags;
  409. RWanStatus = RWAN_STATUS_SUCCESS;
  410. do
  411. {
  412. RWAN_ACQUIRE_CONN_TABLE_LOCK();
  413. pConnObject = RWanGetConnFromId((RWAN_CONN_ID)PtrToUlong(ConnectionContext));
  414. RWAN_RELEASE_CONN_TABLE_LOCK();
  415. if ((pConnObject == NULL) ||
  416. (pConnObject->pAddrObject == NULL))
  417. {
  418. RWanStatus = RWAN_STATUS_BAD_PARAMETER;
  419. break;
  420. }
  421. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  422. pAfChars = &(pConnObject->pAddrObject->pProtocol->pAfInfo->AfChars);
  423. if (pAfChars->pAfSpQueryConnInformation != NULL)
  424. {
  425. RWanStatus = (*pAfChars->pAfSpQueryConnInformation)(
  426. pConnObject->AfSpConnContext,
  427. pInputBuffer,
  428. InputBufferLength,
  429. pOutputBuffer,
  430. pOutputBufferLength
  431. );
  432. }
  433. else
  434. {
  435. RWanStatus = RWAN_STATUS_FAILURE;
  436. }
  437. break;
  438. }
  439. while (FALSE);
  440. return (RWanStatus);
  441. }
  442. PNDIS_BUFFER
  443. RWanCopyFlatToNdis(
  444. IN PNDIS_BUFFER pDestBuffer,
  445. IN PUCHAR pSrcBuffer,
  446. IN UINT LengthToCopy,
  447. IN OUT PUINT pStartOffset,
  448. OUT PUINT pBytesCopied
  449. )
  450. /*++
  451. Routine Description:
  452. Copy from a flat memory buffer to an NDIS buffer chain. It is assumed
  453. that the NDIS buffer chain has enough space.
  454. TBD: Use the TDI function for copying from flat mem to MDL.
  455. Arguments:
  456. pDestBuffer - First buffer in the destination NDIS buffer chain.
  457. pSrcBuffer - Pointer to start of flat memory
  458. LengthToCopy - Max bytes to copy
  459. pStartOffset - Copy offset in first buffer
  460. pBytesCopied - Place to return actual bytes copied
  461. Return Value:
  462. Pointer to buffer in chain where data can be copied into next.
  463. Also, *pStartOffset and *pBytesCopied are set.
  464. --*/
  465. {
  466. UINT CopyLength;
  467. PUCHAR pDest;
  468. UINT Offset;
  469. UINT BytesCopied;
  470. UINT DestSize;
  471. UINT CopySize;
  472. BytesCopied = 0;
  473. Offset = *pStartOffset;
  474. pDest = (PUCHAR)NdisBufferVirtualAddress(pDestBuffer) + Offset;
  475. DestSize = NdisBufferLength(pDestBuffer) - Offset;
  476. for (;;)
  477. {
  478. CopySize = MIN(DestSize, LengthToCopy);
  479. RWAN_COPY_MEM(pDest, pSrcBuffer, CopySize);
  480. pDest += CopySize;
  481. pSrcBuffer += CopySize;
  482. BytesCopied += CopySize;
  483. LengthToCopy -= CopySize;
  484. if (LengthToCopy == 0)
  485. {
  486. break;
  487. }
  488. DestSize -= CopySize;
  489. if (DestSize == 0)
  490. {
  491. pDestBuffer = NDIS_BUFFER_LINKAGE(pDestBuffer);
  492. RWAN_ASSERT(pDestBuffer != NULL);
  493. pDest = NdisBufferVirtualAddress(pDestBuffer);
  494. DestSize = NdisBufferLength(pDestBuffer);
  495. }
  496. }
  497. //
  498. // Prepare return values.
  499. //
  500. *pStartOffset = (UINT)(pDest - (PUCHAR)NdisBufferVirtualAddress(pDestBuffer));
  501. *pBytesCopied = BytesCopied;
  502. return (pDestBuffer);
  503. }