1 /* 2 * This file contains NDIS OID support procedures, common for NDIS5 and NDIS6 3 * 4 * Copyright (c) 2008-2017 Red Hat, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met : 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and / or other materials provided with the distribution. 14 * 3. Neither the names of the copyright holders nor the names of their contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 #include "ParaNdis-Oid.h" 30 31 #ifdef WPP_EVENT_TRACING 32 #include "ParaNdis-Oid.tmh" 33 #endif 34 #include <sal.h> 35 36 static const char VendorName[] = "Red Hat"; 37 38 static UCHAR FORCEINLINE hexdigit(UCHAR nibble) 39 { 40 UCHAR c = nibble & 0xf; 41 c += (c <= 9) ? 0 : 7; 42 c += '0'; 43 return c; 44 } 45 46 /********************************************************** 47 Common implementation of copy operation when OID is set 48 pOid->Flags (if used) controls when the source data may be truncated or padded on copy 49 Parameters: 50 tOidDesc *pOid - descriptor of OID 51 PVOID pDest - buffer to receive data sent by NDIS 52 ULONG ulSize - size of data to copy 53 Return value: 54 SUCCESS or NDIS error code if target buffer size is wrong 55 Rules: 56 57 PDEST <>OK SIZE PAYLOAD SZ 58 NULL any n/a any fail 59 BUFF any 0 any success, none copied 60 BUFF any SZ ==SZ success, copied SZ 61 BUFF !lessok SZ <SZ fail (small), none copied 62 BUFF !moreok SZ >SZ fail (overflow), none copied 63 BUFF lessok SZ <SZ success, SZ cleared, payload sz copied 64 BUFF moreok SZ >SZ success, copied SZ 65 ***************************************************/ 66 NDIS_STATUS ParaNdis_OidSetCopy( 67 tOidDesc *pOid, 68 PVOID pDest, 69 ULONG ulSize) 70 { 71 NDIS_STATUS status = NDIS_STATUS_SUCCESS; 72 if (!pDest) 73 { 74 status = NDIS_STATUS_INVALID_OID; 75 *(pOid->pBytesRead) = 0; 76 *(pOid->pBytesNeeded) = 0; 77 } 78 else if (ulSize) 79 { 80 if (pOid->InformationBufferLength < ulSize) 81 { 82 if (pOid->ulToDoFlags & ohfSetLessOK) 83 { 84 *(pOid->pBytesRead) = pOid->InformationBufferLength; 85 NdisZeroMemory(pDest, ulSize); 86 NdisMoveMemory(pDest, pOid->InformationBuffer, pOid->InformationBufferLength); 87 } 88 else 89 { 90 status = NDIS_STATUS_BUFFER_TOO_SHORT; 91 *(pOid->pBytesRead) = 0; 92 *(pOid->pBytesNeeded) = ulSize; 93 } 94 } 95 else if (pOid->InformationBufferLength == ulSize || (pOid->ulToDoFlags & ohfSetMoreOK)) 96 { 97 *(pOid->pBytesRead) = ulSize; 98 NdisMoveMemory(pDest, pOid->InformationBuffer, ulSize); 99 } 100 else 101 { 102 status = NDIS_STATUS_BUFFER_OVERFLOW; 103 *(pOid->pBytesNeeded) = ulSize; 104 *(pOid->pBytesRead) = 0; 105 } 106 } 107 else 108 { 109 *(pOid->pBytesRead) = pOid->InformationBufferLength; 110 } 111 return status; 112 } 113 114 115 /********************************************************** 116 Common handler of setting packet filter 117 ***********************************************************/ 118 NDIS_STATUS ParaNdis_OnSetPacketFilter(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 119 { 120 ULONG newValue; 121 NDIS_STATUS status = ParaNdis_OidSetCopy( 122 pOid, 123 &newValue, 124 sizeof(newValue)); 125 126 if (newValue & ~PARANDIS_PACKET_FILTERS) 127 status = NDIS_STATUS_INVALID_DATA; 128 129 if (status == NDIS_STATUS_SUCCESS) 130 { 131 pContext->PacketFilter = newValue; 132 DPrintf(1, ("[%s] PACKET FILTER SET TO %x", __FUNCTION__, pContext->PacketFilter)); 133 ParaNdis_UpdateDeviceFilters(pContext); 134 } 135 return status; 136 } 137 138 void ParaNdis_FillPowerCapabilities(PNDIS_PNP_CAPABILITIES pCaps) 139 { 140 NdisZeroMemory(pCaps, sizeof(*pCaps)); 141 pCaps->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified; 142 pCaps->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified; 143 pCaps->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified; 144 } 145 146 147 /********************************************************** 148 Common handler of setting multicast list 149 ***********************************************************/ 150 NDIS_STATUS ParaNdis_OnOidSetMulticastList(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 151 { 152 NDIS_STATUS status; 153 status = ParaNdis_SetMulticastList( 154 pContext, 155 pOid->InformationBuffer, 156 pOid->InformationBufferLength, 157 pOid->pBytesRead, 158 pOid->pBytesNeeded); 159 ParaNdis_UpdateDeviceFilters(pContext); 160 return status; 161 } 162 163 /********************************************************** 164 Common helper of copy operation on GET OID 165 Copies data from specified location to NDIS buffer 166 64-bit variable will be casted to 32-bit, if specified on pOid->Flags 167 168 Parameters: 169 tOidDesc *pOid - descriptor of OID 170 PVOID pInfo - source to copy from 171 ULONG ulSize - source info size 172 Return value: 173 SUCCESS or kind of failure when the dest buffer size is wrong 174 Comments: 175 pInfo must be non-NULL, otherwise error returned 176 ulSize may be 0, then SUCCESS returned without copy 177 ***********************************************************/ 178 NDIS_STATUS ParaNdis_OidQueryCopy( 179 tOidDesc *pOid, 180 PVOID pInfo, 181 ULONG ulSize, 182 BOOLEAN bFreeInfo) 183 { 184 NDIS_STATUS status = NDIS_STATUS_SUCCESS; 185 *(pOid->pBytesNeeded) = ulSize; 186 if (!pInfo) 187 { 188 status = NDIS_STATUS_INVALID_OID; 189 *(pOid->pBytesWritten) = 0; 190 *(pOid->pBytesNeeded) = 0; 191 } 192 else if (pOid->InformationBufferLength >= ulSize) 193 { 194 if (ulSize) NdisMoveMemory(pOid->InformationBuffer, pInfo, ulSize); 195 *(pOid->pBytesWritten) = ulSize; 196 *(pOid->pBytesNeeded) = 0; 197 } 198 else if ((pOid->ulToDoFlags & ohfQuery3264) && pOid->InformationBufferLength == sizeof(ULONG) && ulSize == sizeof(ULONG64)) 199 { 200 ULONG64 u64 = *(ULONG64 *)pInfo; 201 ULONG ul = (ULONG)u64; 202 NdisMoveMemory(pOid->InformationBuffer, &ul, sizeof(ul)); 203 *(pOid->pBytesWritten) = sizeof(ul); 204 } 205 else 206 { 207 status = NDIS_STATUS_BUFFER_TOO_SHORT; 208 *(pOid->pBytesWritten) = 0; 209 } 210 if (bFreeInfo && pInfo) 211 { 212 NdisFreeMemory(pInfo, 0, 0); 213 } 214 return status; 215 } 216 217 /********************************************************** 218 Common handler of Oid queries 219 Parameters: 220 context 221 tOidDesc *pOid - filled descriptor of OID operation 222 Return value: 223 SUCCESS or kind of failure 224 ***********************************************************/ 225 NDIS_STATUS ParaNdis_OidQueryCommon(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 226 { 227 NDIS_STATUS status = NDIS_STATUS_SUCCESS; 228 PVOID pInfo = NULL; 229 ULONG ulSize = 0; 230 BOOLEAN bFreeInfo = FALSE; 231 union _tagtemp 232 { 233 NDIS_MEDIUM Medium; 234 ULONG64 ul64; 235 ULONG ul; 236 USHORT us; 237 NDIS_PNP_CAPABILITIES PMCaps; 238 } u; 239 #if defined(_MSC_VER) && !defined(__clang__) 240 #define CONCATFIELD(object, field) object.##field 241 #else 242 #define CONCATFIELD(object, field) object.field 243 #endif 244 #define SETINFO(field, value) pInfo = CONCATFIELD(&u, field); ulSize = sizeof(CONCATFIELD(u, field)); CONCATFIELD(u, field) = (value) 245 switch (pOid->Oid) 246 { 247 case OID_GEN_SUPPORTED_LIST: 248 ParaNdis_GetSupportedOid(&pInfo, &ulSize); 249 break; 250 case OID_GEN_HARDWARE_STATUS: 251 SETINFO(ul, NdisHardwareStatusReady); 252 break; 253 case OID_GEN_MEDIA_SUPPORTED: 254 __fallthrough; 255 case OID_GEN_MEDIA_IN_USE: 256 SETINFO(Medium, NdisMedium802_3); 257 break; 258 case OID_GEN_MAXIMUM_LOOKAHEAD: 259 SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS); 260 break; 261 case OID_GEN_MAXIMUM_FRAME_SIZE: 262 SETINFO(ul, pContext->MaxPacketSize.nMaxDataSize); 263 break; 264 case OID_GEN_TRANSMIT_BUFFER_SPACE: 265 SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS * pContext->nofFreeTxDescriptors); 266 break; 267 case OID_GEN_RECEIVE_BUFFER_SPACE: 268 SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS * pContext->NetMaxReceiveBuffers); 269 break; 270 case OID_GEN_RECEIVE_BLOCK_SIZE: 271 __fallthrough; 272 case OID_GEN_TRANSMIT_BLOCK_SIZE: 273 __fallthrough; 274 case OID_GEN_MAXIMUM_TOTAL_SIZE: 275 SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS); 276 break; 277 case OID_GEN_TRANSMIT_QUEUE_LENGTH: 278 // TODO: this is not completely correct, but only if 279 // the TX queue is not full 280 SETINFO(ul, pContext->maxFreeTxDescriptors - pContext->nofFreeTxDescriptors); 281 break; 282 case OID_GEN_VENDOR_ID: 283 SETINFO(ul, 0x00ffffff); 284 break; 285 case OID_GEN_VENDOR_DESCRIPTION: 286 pInfo = (PVOID)VendorName; 287 ulSize = sizeof(VendorName); 288 break; 289 290 case OID_GEN_VENDOR_DRIVER_VERSION: 291 SETINFO(ul, (NDIS_MINIPORT_MAJOR_VERSION << 16) | NDIS_MINIPORT_MINOR_VERSION); 292 break; 293 case OID_GEN_CURRENT_PACKET_FILTER: 294 pInfo = &pContext->PacketFilter; 295 ulSize = sizeof(pContext->PacketFilter); 296 break; 297 case OID_GEN_DRIVER_VERSION: 298 SETINFO(us, ((NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION)); 299 break; 300 case OID_GEN_MAC_OPTIONS: 301 { 302 ULONG options = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 303 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | 304 NDIS_MAC_OPTION_NO_LOOPBACK; 305 if (IsPrioritySupported(pContext)) 306 options |= NDIS_MAC_OPTION_8021P_PRIORITY; 307 if (IsVlanSupported(pContext)) 308 options |= NDIS_MAC_OPTION_8021Q_VLAN; 309 SETINFO(ul, options); 310 } 311 break; 312 case OID_GEN_MEDIA_CONNECT_STATUS: 313 SETINFO(ul, pContext->bConnected ? NdisMediaStateConnected : NdisMediaStateDisconnected); 314 //NdisMediaStateConnected: 315 break; 316 case OID_GEN_MAXIMUM_SEND_PACKETS: 317 // NDIS ignores it for deserialized drivers 318 SETINFO(ul,pContext->nofFreeTxDescriptors); 319 break; 320 case OID_802_3_PERMANENT_ADDRESS: 321 pInfo = pContext->PermanentMacAddress; 322 ulSize = sizeof(pContext->PermanentMacAddress); 323 break; 324 case OID_802_3_CURRENT_ADDRESS: 325 pInfo = pContext->CurrentMacAddress; 326 ulSize = sizeof(pContext->CurrentMacAddress); 327 break; 328 case OID_PNP_QUERY_POWER: 329 // size if 0, just to indicate success 330 pInfo = &status; 331 break; 332 case OID_GEN_DIRECTED_BYTES_XMIT: 333 SETINFO(ul64, pContext->Statistics.ifHCOutUcastOctets); 334 break; 335 case OID_GEN_DIRECTED_FRAMES_XMIT: 336 SETINFO(ul64, pContext->Statistics.ifHCOutUcastPkts); 337 break; 338 case OID_GEN_MULTICAST_BYTES_XMIT: 339 SETINFO(ul64, pContext->Statistics.ifHCOutMulticastOctets); 340 break; 341 case OID_GEN_MULTICAST_FRAMES_XMIT: 342 SETINFO(ul64, pContext->Statistics.ifHCOutMulticastPkts); 343 break; 344 case OID_GEN_BROADCAST_BYTES_XMIT: 345 SETINFO(ul64, pContext->Statistics.ifHCOutBroadcastOctets); 346 break; 347 case OID_GEN_BROADCAST_FRAMES_XMIT: 348 SETINFO(ul64, pContext->Statistics.ifHCOutBroadcastPkts); 349 break; 350 case OID_GEN_DIRECTED_BYTES_RCV: 351 SETINFO(ul64, pContext->Statistics.ifHCInUcastOctets); 352 break; 353 case OID_GEN_DIRECTED_FRAMES_RCV: 354 SETINFO(ul64, pContext->Statistics.ifHCInUcastPkts); 355 break; 356 case OID_GEN_MULTICAST_BYTES_RCV: 357 SETINFO(ul64, pContext->Statistics.ifHCInMulticastOctets); 358 break; 359 case OID_GEN_MULTICAST_FRAMES_RCV: 360 SETINFO(ul64, pContext->Statistics.ifHCInMulticastPkts); 361 break; 362 case OID_GEN_BROADCAST_BYTES_RCV: 363 SETINFO(ul64, pContext->Statistics.ifHCInBroadcastOctets); 364 break; 365 case OID_GEN_BROADCAST_FRAMES_RCV: 366 SETINFO(ul64, pContext->Statistics.ifHCInBroadcastPkts); 367 break; 368 case OID_GEN_XMIT_OK: 369 SETINFO(ul64, 370 pContext->Statistics.ifHCOutUcastPkts + 371 pContext->Statistics.ifHCOutMulticastPkts + 372 pContext->Statistics.ifHCOutBroadcastPkts); 373 break; 374 case OID_GEN_RCV_OK: 375 SETINFO(ul64, 376 pContext->Statistics.ifHCInUcastPkts + 377 pContext->Statistics.ifHCInMulticastPkts + 378 pContext->Statistics.ifHCInBroadcastPkts); 379 DPrintf(4, ("[%s] Total frames %I64u", __FUNCTION__, u.ul64)); 380 break; 381 case OID_GEN_XMIT_ERROR: 382 SETINFO(ul64, pContext->Statistics.ifOutErrors ); 383 break; 384 case OID_GEN_RCV_ERROR: 385 __fallthrough; 386 case OID_GEN_RCV_NO_BUFFER: 387 __fallthrough; 388 case OID_802_3_RCV_OVERRUN: 389 __fallthrough; 390 case OID_GEN_RCV_CRC_ERROR: 391 __fallthrough; 392 case OID_802_3_RCV_ERROR_ALIGNMENT: 393 __fallthrough; 394 case OID_802_3_XMIT_UNDERRUN: 395 __fallthrough; 396 case OID_802_3_XMIT_ONE_COLLISION: 397 __fallthrough; 398 case OID_802_3_XMIT_DEFERRED: 399 __fallthrough; 400 case OID_802_3_XMIT_MAX_COLLISIONS: 401 __fallthrough; 402 case OID_802_3_XMIT_MORE_COLLISIONS: 403 __fallthrough; 404 case OID_802_3_XMIT_HEARTBEAT_FAILURE: 405 __fallthrough; 406 case OID_802_3_XMIT_TIMES_CRS_LOST: 407 __fallthrough; 408 case OID_802_3_XMIT_LATE_COLLISIONS: 409 SETINFO(ul64, 0); 410 break; 411 case OID_802_3_MULTICAST_LIST: 412 pInfo = pContext->MulticastData.MulticastList; 413 ulSize = pContext->MulticastData.nofMulticastEntries * ETH_LENGTH_OF_ADDRESS; 414 break; 415 case OID_802_3_MAXIMUM_LIST_SIZE: 416 SETINFO(ul, PARANDIS_MULTICAST_LIST_SIZE); 417 break; 418 case OID_PNP_CAPABILITIES: 419 pInfo = &u.PMCaps; 420 ulSize = sizeof(u.PMCaps); 421 ParaNdis_FillPowerCapabilities(&u.PMCaps); 422 break; 423 case OID_802_3_MAC_OPTIONS: 424 SETINFO(ul, 0); 425 break; 426 case OID_GEN_VLAN_ID: 427 SETINFO(ul, pContext->VlanId); 428 if (!IsVlanSupported(pContext)) 429 status = NDIS_STATUS_NOT_SUPPORTED; 430 break; 431 case OID_GEN_CURRENT_LOOKAHEAD: 432 if (!pContext->DummyLookAhead) pContext->DummyLookAhead = pContext->MaxPacketSize.nMaxFullSizeOS; 433 pInfo = &pContext->DummyLookAhead; 434 ulSize = sizeof(pContext->DummyLookAhead); 435 break; 436 case OID_PNP_ENABLE_WAKE_UP: 437 SETINFO(ul, pContext->ulEnableWakeup); 438 break; 439 default: 440 status = NDIS_STATUS_NOT_SUPPORTED; 441 break; 442 } 443 444 if (status == NDIS_STATUS_SUCCESS) 445 { 446 status = ParaNdis_OidQueryCopy(pOid, pInfo, ulSize, bFreeInfo); 447 } 448 449 return status; 450 } 451 452 453 /********************************************************** 454 Just gets OID name 455 ***********************************************************/ 456 const char *ParaNdis_OidName(NDIS_OID oid) 457 { 458 #undef MAKECASE 459 #define MAKECASE(id) case id: return #id; 460 switch (oid) 461 { 462 MAKECASE(OID_GEN_SUPPORTED_LIST) 463 MAKECASE(OID_GEN_HARDWARE_STATUS) 464 MAKECASE(OID_GEN_MEDIA_SUPPORTED) 465 MAKECASE(OID_GEN_MEDIA_IN_USE) 466 MAKECASE(OID_GEN_MAXIMUM_LOOKAHEAD) 467 MAKECASE(OID_GEN_MAXIMUM_FRAME_SIZE) 468 MAKECASE(OID_GEN_LINK_SPEED) 469 MAKECASE(OID_GEN_TRANSMIT_BUFFER_SPACE) 470 MAKECASE(OID_GEN_RECEIVE_BUFFER_SPACE) 471 MAKECASE(OID_GEN_TRANSMIT_BLOCK_SIZE) 472 MAKECASE(OID_GEN_RECEIVE_BLOCK_SIZE) 473 MAKECASE(OID_GEN_VENDOR_ID) 474 MAKECASE(OID_GEN_VENDOR_DESCRIPTION) 475 MAKECASE(OID_GEN_CURRENT_PACKET_FILTER) 476 MAKECASE(OID_GEN_CURRENT_LOOKAHEAD) 477 MAKECASE(OID_GEN_DRIVER_VERSION) 478 MAKECASE(OID_GEN_MAXIMUM_TOTAL_SIZE) 479 MAKECASE(OID_GEN_PROTOCOL_OPTIONS) 480 MAKECASE(OID_GEN_MAC_OPTIONS) 481 MAKECASE(OID_GEN_MEDIA_CONNECT_STATUS) 482 MAKECASE(OID_GEN_MAXIMUM_SEND_PACKETS) 483 MAKECASE(OID_GEN_VENDOR_DRIVER_VERSION) 484 MAKECASE(OID_GEN_SUPPORTED_GUIDS) 485 MAKECASE(OID_GEN_TRANSPORT_HEADER_OFFSET) 486 MAKECASE(OID_GEN_MEDIA_CAPABILITIES) 487 MAKECASE(OID_GEN_PHYSICAL_MEDIUM) 488 MAKECASE(OID_GEN_XMIT_OK) 489 MAKECASE(OID_GEN_RCV_OK) 490 MAKECASE(OID_GEN_XMIT_ERROR) 491 MAKECASE(OID_GEN_RCV_ERROR) 492 MAKECASE(OID_GEN_RCV_NO_BUFFER) 493 MAKECASE(OID_GEN_DIRECTED_BYTES_XMIT) 494 MAKECASE(OID_GEN_DIRECTED_FRAMES_XMIT) 495 MAKECASE(OID_GEN_MULTICAST_BYTES_XMIT) 496 MAKECASE(OID_GEN_MULTICAST_FRAMES_XMIT) 497 MAKECASE(OID_GEN_BROADCAST_BYTES_XMIT) 498 MAKECASE(OID_GEN_BROADCAST_FRAMES_XMIT) 499 MAKECASE(OID_GEN_DIRECTED_BYTES_RCV) 500 MAKECASE(OID_GEN_DIRECTED_FRAMES_RCV) 501 MAKECASE(OID_GEN_MULTICAST_BYTES_RCV) 502 MAKECASE(OID_GEN_MULTICAST_FRAMES_RCV) 503 MAKECASE(OID_GEN_BROADCAST_BYTES_RCV) 504 MAKECASE(OID_GEN_BROADCAST_FRAMES_RCV) 505 MAKECASE(OID_GEN_RCV_CRC_ERROR) 506 MAKECASE(OID_GEN_TRANSMIT_QUEUE_LENGTH) 507 MAKECASE(OID_GEN_GET_TIME_CAPS) 508 MAKECASE(OID_GEN_GET_NETCARD_TIME) 509 MAKECASE(OID_GEN_NETCARD_LOAD) 510 MAKECASE(OID_GEN_DEVICE_PROFILE) 511 MAKECASE(OID_GEN_INIT_TIME_MS) 512 MAKECASE(OID_GEN_RESET_COUNTS) 513 MAKECASE(OID_GEN_MEDIA_SENSE_COUNTS) 514 MAKECASE(OID_GEN_VLAN_ID) 515 MAKECASE(OID_PNP_CAPABILITIES) 516 MAKECASE(OID_PNP_SET_POWER) 517 MAKECASE(OID_PNP_QUERY_POWER) 518 MAKECASE(OID_PNP_ADD_WAKE_UP_PATTERN) 519 MAKECASE(OID_PNP_REMOVE_WAKE_UP_PATTERN) 520 MAKECASE(OID_PNP_ENABLE_WAKE_UP) 521 MAKECASE(OID_802_3_PERMANENT_ADDRESS) 522 MAKECASE(OID_802_3_CURRENT_ADDRESS) 523 MAKECASE(OID_802_3_MULTICAST_LIST) 524 MAKECASE(OID_802_3_MAXIMUM_LIST_SIZE) 525 MAKECASE(OID_802_3_MAC_OPTIONS) 526 MAKECASE(OID_802_3_RCV_ERROR_ALIGNMENT) 527 MAKECASE(OID_802_3_XMIT_ONE_COLLISION) 528 MAKECASE(OID_802_3_XMIT_MORE_COLLISIONS) 529 MAKECASE(OID_802_3_XMIT_DEFERRED) 530 MAKECASE(OID_802_3_XMIT_MAX_COLLISIONS) 531 MAKECASE(OID_802_3_RCV_OVERRUN) 532 MAKECASE(OID_802_3_XMIT_UNDERRUN) 533 MAKECASE(OID_802_3_XMIT_HEARTBEAT_FAILURE) 534 MAKECASE(OID_802_3_XMIT_TIMES_CRS_LOST) 535 MAKECASE(OID_802_3_XMIT_LATE_COLLISIONS) 536 MAKECASE(OID_GEN_MACHINE_NAME) 537 MAKECASE(OID_TCP_TASK_OFFLOAD) 538 MAKECASE(OID_TCP_OFFLOAD_PARAMETERS) 539 MAKECASE(OID_OFFLOAD_ENCAPSULATION) 540 MAKECASE(OID_IP4_OFFLOAD_STATS) 541 MAKECASE(OID_IP6_OFFLOAD_STATS) 542 default: 543 { 544 static UCHAR buffer[9]; 545 UINT i; 546 for (i = 0; i < 8; ++i) 547 { 548 UCHAR nibble = (UCHAR)((oid >> (28 - i * 4)) & 0xf); 549 buffer[i] = hexdigit(nibble); 550 } 551 return (char *)buffer; 552 } 553 } 554 } 555 556 /********************************************************** 557 Checker of valid size of provided wake-up patter 558 Return value: SUCCESS or kind of failure where the buffer is wrong 559 ***********************************************************/ 560 static NDIS_STATUS ValidateWakeupPattern(PNDIS_PM_PACKET_PATTERN p, PULONG pValidSize) 561 { 562 NDIS_STATUS status = NDIS_STATUS_BUFFER_TOO_SHORT; 563 564 if (*pValidSize < sizeof(*p)) 565 { 566 *pValidSize = sizeof(*p); 567 } 568 else 569 { 570 ULONG ul = p->PatternOffset + p->PatternSize; 571 if (*pValidSize >= ul) status = NDIS_STATUS_SUCCESS; 572 *pValidSize = ul; 573 DPrintf(2, ("[%s] pattern of %d at %d, mask %d (%s)", 574 __FUNCTION__, p->PatternSize, p->PatternOffset, p->MaskSize, 575 status == NDIS_STATUS_SUCCESS ? "OK" : "Fail")); 576 } 577 return status; 578 } 579 580 581 /********************************************************** 582 Common handler of wake-up pattern addition 583 ***********************************************************/ 584 NDIS_STATUS ParaNdis_OnAddWakeupPattern(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 585 { 586 NDIS_STATUS status; 587 PNDIS_PM_PACKET_PATTERN pPmPattern = (PNDIS_PM_PACKET_PATTERN) pOid->InformationBuffer; 588 ULONG ulValidSize = pOid->InformationBufferLength; 589 status = ValidateWakeupPattern(pPmPattern, &ulValidSize); 590 if (status == NDIS_STATUS_SUCCESS) 591 { 592 *pOid->pBytesRead = ulValidSize; 593 } 594 else 595 { 596 *pOid->pBytesRead = 0; 597 *pOid->pBytesNeeded = ulValidSize; 598 } 599 // TODO: Apply 600 return status; 601 } 602 603 /********************************************************** 604 Common handler of wake-up pattern removal 605 ***********************************************************/ 606 NDIS_STATUS ParaNdis_OnRemoveWakeupPattern(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 607 { 608 NDIS_STATUS status; 609 PNDIS_PM_PACKET_PATTERN pPmPattern = (PNDIS_PM_PACKET_PATTERN) pOid->InformationBuffer; 610 ULONG ulValidSize = pOid->InformationBufferLength; 611 status = ValidateWakeupPattern(pPmPattern, &ulValidSize); 612 if (status == NDIS_STATUS_SUCCESS) 613 { 614 *pOid->pBytesRead = ulValidSize; 615 } 616 else 617 { 618 *pOid->pBytesRead = 0; 619 *pOid->pBytesNeeded = ulValidSize; 620 } 621 return status; 622 } 623 624 /********************************************************** 625 Common handler of wake-up enabling upon standby 626 ***********************************************************/ 627 NDIS_STATUS ParaNdis_OnEnableWakeup(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 628 { 629 NDIS_STATUS status = ParaNdis_OidSetCopy(pOid, &pContext->ulEnableWakeup, sizeof(pContext->ulEnableWakeup)); 630 if (status == NDIS_STATUS_SUCCESS) 631 { 632 DPrintf(0, ("[%s] new value %lX", __FUNCTION__, pContext->ulEnableWakeup)); 633 } 634 return status; 635 } 636 637 /********************************************************** 638 Dummy implementation 639 ***********************************************************/ 640 NDIS_STATUS ParaNdis_OnSetLookahead(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 641 { 642 return ParaNdis_OidSetCopy(pOid, &pContext->DummyLookAhead, sizeof(pContext->DummyLookAhead)); 643 } 644 645 NDIS_STATUS ParaNdis_OnSetVlanId(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) 646 { 647 NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED; 648 if (IsVlanSupported(pContext)) 649 { 650 status = ParaNdis_OidSetCopy(pOid, &pContext->VlanId, sizeof(pContext->VlanId)); 651 pContext->VlanId &= 0xfff; 652 DPrintf(0, ("[%s] new value %d on MAC %X", __FUNCTION__, pContext->VlanId, pContext->CurrentMacAddress[5])); 653 ParaNdis_DeviceFiltersUpdateVlanId(pContext); 654 } 655 return status; 656 } 657 658 /********************************************************** 659 Retrieves support rules for specific OID 660 ***********************************************************/ 661 void ParaNdis_GetOidSupportRules(NDIS_OID oid, tOidWhatToDo *pRule, const tOidWhatToDo *Table) 662 { 663 static const tOidWhatToDo defaultRule = { 0, 0, 0, 0, 0, NULL, "Unknown OID" }; 664 UINT i; 665 *pRule = defaultRule; 666 pRule->oid = oid; 667 668 for (i = 0; Table[i].oid != 0; ++i) 669 { 670 if (Table[i].oid == oid) 671 { 672 *pRule = Table[i]; 673 break; 674 } 675 } 676 pRule->name = ParaNdis_OidName(oid); 677 } 678