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.

602 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. dlcinfo.c
  5. Abstract:
  6. The module implements the Query/Set information commands.
  7. It also provides the statistics services for DLC api.
  8. Contents:
  9. GetDlcErrorCounters
  10. DlcQueryInformation
  11. DlcSetInformation
  12. GetOpenSapAndStationCount
  13. SetupGroupSaps
  14. Author:
  15. Antti Saarenheimo (o-anttis) 29-AUG-1991
  16. Revision History:
  17. --*/
  18. #include <dlc.h>
  19. static ULONG aTokenringLogOid[ADAPTER_ERROR_COUNTERS] = {
  20. OID_802_5_LINE_ERRORS,
  21. 0,
  22. OID_802_5_BURST_ERRORS,
  23. OID_802_5_AC_ERRORS,
  24. OID_802_5_ABORT_DELIMETERS,
  25. 0,
  26. OID_802_5_LOST_FRAMES,
  27. OID_GEN_RCV_NO_BUFFER,
  28. OID_802_5_FRAME_COPIED_ERRORS,
  29. OID_802_5_FREQUENCY_ERRORS,
  30. OID_802_5_TOKEN_ERRORS
  31. };
  32. static ULONG aEthernetLogOid[ADAPTER_ERROR_COUNTERS] = {
  33. OID_802_3_XMIT_TIMES_CRS_LOST,
  34. 0,
  35. OID_802_3_RCV_ERROR_ALIGNMENT,
  36. 0,
  37. OID_GEN_XMIT_ERROR,
  38. 0,
  39. OID_802_3_XMIT_MAX_COLLISIONS,
  40. OID_GEN_RCV_NO_BUFFER,
  41. 0,
  42. 0,
  43. 0
  44. };
  45. static ULONG aFddiLogOid[ADAPTER_ERROR_COUNTERS] = {
  46. 0,
  47. 0,
  48. 0,
  49. 0,
  50. 0,
  51. 0,
  52. 0,
  53. 0,
  54. 0,
  55. 0,
  56. 0
  57. };
  58. VOID
  59. GetDlcErrorCounters(
  60. IN PDLC_FILE_CONTEXT pFileContext,
  61. IN PUCHAR pAdapterErrors
  62. )
  63. /*++
  64. Routine Description:
  65. Procedure reads the cumulative 32-bit adapter error counters from
  66. ethernet or token-ring adapter and returns 8-bit DLC error counters,
  67. that supports read and read & reset commands. It also maintains
  68. local copies of the NDIS error counters in the process specific
  69. adapter context, because NDIS counters cannot be reset.
  70. Arguments:
  71. pFileContext - DLC address object
  72. pAdapterErrors - DLC errors counters, if NULL => NDIS values are
  73. copied to file context.
  74. Return Value:
  75. None.
  76. --*/
  77. {
  78. LLC_NDIS_REQUEST Request;
  79. PULONG pOidBuffer;
  80. ULONG counter;
  81. UINT i;
  82. UINT Status;
  83. ASSUME_IRQL(DISPATCH_LEVEL);
  84. //
  85. // Token-ring and ethernet uses different error counters
  86. //
  87. switch (pFileContext->ActualNdisMedium) {
  88. case NdisMedium802_3:
  89. pOidBuffer = aEthernetLogOid;
  90. break;
  91. case NdisMedium802_5:
  92. pOidBuffer = aTokenringLogOid;
  93. break;
  94. case NdisMediumFddi:
  95. pOidBuffer = aFddiLogOid;
  96. break;
  97. }
  98. //
  99. // read all error counters having non null NDIS OID and
  100. // decrement the previous error count value from it.
  101. // Overflowed DLC error counter is set 255 (the maximum).
  102. //
  103. Request.Ndis.RequestType = NdisRequestQueryInformation;
  104. Request.Ndis.DATA.QUERY_INFORMATION.InformationBuffer = &counter;
  105. Request.Ndis.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(counter);
  106. for (i = 0; i < ADAPTER_ERROR_COUNTERS; i++) {
  107. if (pOidBuffer[i] != 0) {
  108. Request.Ndis.DATA.QUERY_INFORMATION.Oid = pOidBuffer[i];
  109. LEAVE_DLC(pFileContext);
  110. RELEASE_DRIVER_LOCK();
  111. Status = LlcNdisRequest(pFileContext->pBindingContext, &Request);
  112. ACQUIRE_DRIVER_LOCK();
  113. ENTER_DLC(pFileContext);
  114. if (Status != STATUS_SUCCESS) {
  115. #if DBG
  116. if ( Status != STATUS_NOT_SUPPORTED ){
  117. // Only print real errors.
  118. DbgPrint("DLC.GetDlcErrorCounters: LlcNdisRequest returns %x\n", Status);
  119. }
  120. #endif
  121. counter = 0;
  122. } else if ((counter - pFileContext->NdisErrorCounters[i] > 255)
  123. && (pAdapterErrors != NULL)) {
  124. counter = 255;
  125. } else {
  126. counter -= pFileContext->NdisErrorCounters[i];
  127. }
  128. if (pAdapterErrors != NULL) {
  129. pAdapterErrors[i] = (UCHAR)counter;
  130. }
  131. pFileContext->NdisErrorCounters[i] += counter;
  132. }
  133. }
  134. }
  135. NTSTATUS
  136. DlcQueryInformation(
  137. IN PIRP pIrp,
  138. IN PDLC_FILE_CONTEXT pFileContext,
  139. IN PNT_DLC_PARMS pDlcParms,
  140. IN ULONG InputBufferLength,
  141. IN ULONG OutputBufferLength
  142. )
  143. /*++
  144. Routine Description:
  145. The routine returns the DLC specific information of any DLC object.
  146. Arguments:
  147. pIrp - current io request packet
  148. pFileContext - DLC address object
  149. pDlcParms - the current parameter block
  150. InputBufferLength - the length of input parameters
  151. OutputBufferLength - the length of output parameters
  152. Return Value:
  153. NTSTATUS:
  154. STATUS_SUCCESS
  155. STATUS_INVALID_COMMAND
  156. --*/
  157. {
  158. NTSTATUS Status = STATUS_SUCCESS;
  159. PVOID hClientHandle = pFileContext->pBindingContext;
  160. PDLC_OBJECT pDlcObject;
  161. PLLC_ADAPTER_DLC_INFO pDlcAdapter;
  162. UNREFERENCED_PARAMETER(pIrp);
  163. UNREFERENCED_PARAMETER(InputBufferLength);
  164. ASSUME_IRQL(DISPATCH_LEVEL);
  165. //
  166. // NOTE: DlcQueryBuffer output buffer size was not checked by
  167. // DlcDeviceIoControl. For each class we check the size
  168. // based on what it will copy. Although it did check that
  169. // the input buffer size was at least NT_DLC_QUERY_INFORMATION_INPUT
  170. // size.
  171. //
  172. switch (pDlcParms->DlcGetInformation.Header.InfoClass) {
  173. case DLC_INFO_CLASS_DLC_ADAPTER:
  174. // union NT_DLC_PARMS
  175. // LLC_ADAPTER_DLC_INFO
  176. if (OutputBufferLength < sizeof(LLC_ADAPTER_DLC_INFO))
  177. {
  178. Status = STATUS_BUFFER_TOO_SMALL;
  179. break;
  180. }
  181. //
  182. // The output data is just written to the
  183. // beginning of the current system buffer.
  184. //
  185. pDlcAdapter = (PLLC_ADAPTER_DLC_INFO)pDlcParms;
  186. GetOpenSapAndStationCount(pFileContext,
  187. &pDlcAdapter->OpenSaps,
  188. (PUCHAR)&pDlcAdapter->OpenStations
  189. );
  190. pDlcAdapter->MaxSap = 127;
  191. pDlcAdapter->MaxStations = 255;
  192. pDlcAdapter->AvailStations = (UCHAR)255 - pDlcAdapter->OpenStations;
  193. break;
  194. case DLC_INFO_CLASS_ADAPTER_LOG:
  195. // union NT_DLC_PARMS (pDlcParms)
  196. // union NT_DLC_QUERY_INFORMATION_PARMS DlcGetInformation
  197. // union NT_DLC_QUERY_INFORMATION_OUTPUT Info
  198. // union LLC_ADAPTER_LOG AdapterLog
  199. if (OutputBufferLength < sizeof(LLC_ADAPTER_LOG))
  200. {
  201. Status = STATUS_BUFFER_TOO_SMALL;
  202. break;
  203. }
  204. GetDlcErrorCounters(pFileContext, (PUCHAR)&pDlcParms->DlcGetInformation);
  205. break;
  206. case DLC_INFO_CLASS_LINK_STATION:
  207. // union NT_DLC_PARMS (pDlcParms)
  208. // union NT_DLC_QUERY_INFORMATION_PARMS DlcGetInformation
  209. // union NT_DLC_QUERY_INFORMATION_OUTPUT Info
  210. // struct _DlcLinkInfoGet
  211. // USHORT MaxInformationField
  212. if (OutputBufferLength < sizeof(USHORT))
  213. {
  214. Status = STATUS_BUFFER_TOO_SMALL;
  215. break;
  216. }
  217. Status = GetLinkStation(pFileContext,
  218. pDlcParms->DlcGetInformation.Header.StationId,
  219. &pDlcObject
  220. );
  221. if (Status == STATUS_SUCCESS) {
  222. //
  223. // Round always the information field length to the full
  224. // dword even number => some copy operations may be much
  225. // faster (usually not, but worth of effor in any way)
  226. //
  227. pDlcParms->DlcGetInformation.Info.Link.MaxInformationField = (USHORT)(pDlcObject->u.Link.MaxInfoFieldLength & -3);
  228. }
  229. break;
  230. case DLC_INFO_CLASS_STATISTICS:
  231. case DLC_INFO_CLASS_STATISTICS_RESET:
  232. Status = GetStation(pFileContext,
  233. pDlcParms->DlcGetInformation.Header.StationId,
  234. &pDlcObject
  235. );
  236. if (Status != STATUS_SUCCESS) {
  237. return Status;
  238. }
  239. hClientHandle = pDlcObject->hLlcObject;
  240. //
  241. // **** FALL THROUGH ****
  242. //
  243. default:
  244. //
  245. // LLC will return invalid command, if it is not supported
  246. //
  247. LEAVE_DLC(pFileContext);
  248. RELEASE_DRIVER_LOCK();
  249. //
  250. // LlcQueryInformation validates buffer size before copying.
  251. //
  252. Status = LlcQueryInformation(hClientHandle,
  253. pDlcParms->DlcGetInformation.Header.InfoClass,
  254. (PLLC_QUERY_INFO_BUFFER)&(pDlcParms->DlcGetInformation),
  255. (UINT)OutputBufferLength
  256. );
  257. ACQUIRE_DRIVER_LOCK();
  258. ENTER_DLC(pFileContext);
  259. break;
  260. }
  261. return (NTSTATUS)Status;
  262. }
  263. NTSTATUS
  264. DlcSetInformation(
  265. IN PIRP pIrp,
  266. IN PDLC_FILE_CONTEXT pFileContext,
  267. IN PNT_DLC_PARMS pDlcParms,
  268. IN ULONG InputBufferLength,
  269. IN ULONG OutputBufferLength
  270. )
  271. /*++
  272. Routine Description:
  273. The routine sets new parameter values for the DLC objects.
  274. Arguments:
  275. pIrp - current io request packet
  276. pFileContext - DLC address object
  277. pDlcParms - the current parameter block
  278. InputBufferLength - the length of input parameters
  279. Return Value:
  280. NTSTATUS
  281. STATUS_SUCCESS
  282. STATUS_INVALID_COMMAND
  283. --*/
  284. {
  285. NTSTATUS Status = STATUS_SUCCESS;
  286. PDLC_OBJECT pDlcObject;
  287. UNREFERENCED_PARAMETER(pIrp);
  288. UNREFERENCED_PARAMETER(InputBufferLength);
  289. UNREFERENCED_PARAMETER(OutputBufferLength);
  290. ASSUME_IRQL(DISPATCH_LEVEL);
  291. switch (pDlcParms->DlcSetInformation.Header.InfoClass) {
  292. case DLC_INFO_CLASS_LINK_STATION:
  293. case DLC_INFO_CLASS_DIRECT_INFO:
  294. Status = GetStation(pFileContext,
  295. pDlcParms->DlcSetInformation.Header.StationId,
  296. &pDlcObject
  297. );
  298. if (Status != STATUS_SUCCESS) {
  299. return Status;
  300. }
  301. LEAVE_DLC(pFileContext);
  302. Status = LlcSetInformation(pDlcObject->hLlcObject,
  303. pDlcParms->DlcSetInformation.Header.InfoClass,
  304. (PLLC_SET_INFO_BUFFER)&(
  305. pDlcParms->DlcSetInformation.Info.LinkStation),
  306. sizeof(DLC_LINK_PARAMETERS)
  307. );
  308. break;
  309. case DLC_INFO_CLASS_DLC_TIMERS:
  310. LEAVE_DLC(pFileContext);
  311. Status = LlcSetInformation(pFileContext->pBindingContext,
  312. pDlcParms->DlcSetInformation.Header.InfoClass,
  313. (PLLC_SET_INFO_BUFFER)&(pDlcParms->DlcSetInformation.Info.TimerParameters),
  314. sizeof(LLC_TICKS)
  315. );
  316. break;
  317. case DLC_INFO_CLASS_SET_FUNCTIONAL:
  318. case DLC_INFO_CLASS_RESET_FUNCTIONAL:
  319. case DLC_INFO_CLASS_SET_GROUP:
  320. case DLC_INFO_CLASS_SET_MULTICAST:
  321. LEAVE_DLC(pFileContext);
  322. Status = LlcSetInformation(pFileContext->pBindingContext,
  323. pDlcParms->DlcSetInformation.Header.InfoClass,
  324. (PLLC_SET_INFO_BUFFER)&(pDlcParms->DlcSetInformation.Info.Broadcast),
  325. sizeof(TR_BROADCAST_ADDRESS)
  326. );
  327. break;
  328. case DLC_INFO_CLASS_GROUP:
  329. //
  330. // Setup DLC group SAPs. Group saps are used as a common address
  331. // of a SAP group. They can only receive frames.
  332. //
  333. Status = GetStation(pFileContext,
  334. pDlcParms->DlcSetInformation.Header.StationId,
  335. &pDlcObject
  336. );
  337. if (Status != STATUS_SUCCESS) {
  338. return Status;
  339. }
  340. Status = SetupGroupSaps(pFileContext,
  341. pDlcObject,
  342. (UINT)pDlcParms->DlcSetInformation.Info.Sap.GroupCount,
  343. (PUCHAR)pDlcParms->DlcSetInformation.Info.Sap.GroupList
  344. );
  345. LEAVE_DLC(pFileContext);
  346. break;
  347. default:
  348. LEAVE_DLC(pFileContext);
  349. Status = DLC_STATUS_INVALID_COMMAND;
  350. break;
  351. };
  352. ENTER_DLC(pFileContext);
  353. return Status;
  354. }
  355. //
  356. // Function returns the number of open sap and link
  357. // stations for a dlc application.
  358. //
  359. VOID
  360. GetOpenSapAndStationCount(
  361. IN PDLC_FILE_CONTEXT pFileContext,
  362. OUT PUCHAR pOpenSaps,
  363. OUT PUCHAR pOpenStations
  364. )
  365. {
  366. UINT i, SapCount = 0;
  367. for (i = 1; i < MAX_SAP_STATIONS; i++) {
  368. if (pFileContext->SapStationTable[i] != NULL) {
  369. SapCount++;
  370. }
  371. }
  372. *pOpenSaps = (UCHAR)SapCount;
  373. if (pFileContext->SapStationTable[0] != NULL) {
  374. SapCount++;
  375. }
  376. *pOpenStations = (UCHAR)(pFileContext->DlcObjectCount - SapCount);
  377. }
  378. NTSTATUS
  379. SetupGroupSaps(
  380. IN PDLC_FILE_CONTEXT pFileContext,
  381. IN PDLC_OBJECT pDlcObject,
  382. IN UINT GroupSapCount,
  383. IN PUCHAR pGroupSapList
  384. )
  385. /*++
  386. Routine Description:
  387. The routine deletes the current group saps list and
  388. and new group saps. Fi the new group sap list is empty, then
  389. we just delete all current group saps.
  390. Arguments:
  391. pFileContext - DLC context
  392. pDlcObject - SAP object
  393. GroupSapCount - number of new group saps
  394. pGroupSapList - list of new group saps
  395. Return Value:
  396. NTSTATUS:
  397. STATUS_SUCCESS
  398. STATUS_INVALID_COMMAND
  399. --*/
  400. {
  401. UINT i;
  402. UINT OpenOptions;
  403. //
  404. // We must first remove all old groups sap defined for the
  405. // sap station (if any)
  406. //
  407. if (pDlcObject->u.Sap.GroupSapHandleList != NULL) {
  408. for (i = 0; i < pDlcObject->u.Sap.GroupSapCount; i++) {
  409. if (pDlcObject->u.Sap.GroupSapHandleList[i] != NULL) {
  410. LEAVE_DLC(pFileContext);
  411. LlcCloseStation(pDlcObject->u.Sap.GroupSapHandleList[i], NULL);
  412. ENTER_DLC(pFileContext);
  413. }
  414. }
  415. FREE_MEMORY_FILE(pDlcObject->u.Sap.GroupSapHandleList);
  416. pDlcObject->u.Sap.GroupSapHandleList = NULL;
  417. }
  418. //
  419. // Note: the old group saps can be deleted with a null list!
  420. //
  421. pDlcObject->u.Sap.GroupSapCount = (UCHAR)GroupSapCount;
  422. if (GroupSapCount != 0) {
  423. pDlcObject->u.Sap.GroupSapHandleList = (PVOID*)ALLOCATE_ZEROMEMORY_FILE(
  424. GroupSapCount
  425. * sizeof(PVOID)
  426. );
  427. if (pDlcObject->u.Sap.GroupSapHandleList == NULL) {
  428. return DLC_STATUS_NO_MEMORY;
  429. }
  430. //
  431. // The groups sap implementation is based on the fact,
  432. // that the lower module things to run a normal sap.
  433. // The routing of UI, TEST and XID frames for all
  434. // saps sends the incoming U-frames automatically
  435. // all real saps registered to a sap. This method
  436. // could theoretically use very much memory if there were
  437. // very many saps and group saps (eg: 50 * 50 = 2500 * 100),
  438. // but that situation is actually impossible.
  439. // SNA saps (3) have one command group sap and even SNA
  440. // sap is very rarely used (not used by CommServer)
  441. //
  442. for (i = 0; i < pDlcObject->u.Sap.GroupSapCount; i++) {
  443. UINT Status;
  444. OpenOptions = 0;
  445. if (~(pDlcObject->u.Sap.OptionsPriority & XID_HANDLING_BIT)) {
  446. OpenOptions = LLC_HANDLE_XID_COMMANDS;
  447. }
  448. LEAVE_DLC(pFileContext);
  449. Status = LlcOpenSap(pFileContext->pBindingContext,
  450. (PVOID)pDlcObject,
  451. (UINT)pGroupSapList[i] | 1,
  452. OpenOptions,
  453. &pDlcObject->u.Sap.GroupSapHandleList[i]
  454. );
  455. ENTER_DLC(pFileContext);
  456. if (Status != STATUS_SUCCESS) {
  457. return Status;
  458. }
  459. }
  460. }
  461. return STATUS_SUCCESS;
  462. }