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
hexdigit(UCHAR nibble)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 ***************************************************/
ParaNdis_OidSetCopy(tOidDesc * pOid,PVOID pDest,ULONG ulSize)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 ***********************************************************/
ParaNdis_OnSetPacketFilter(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)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
ParaNdis_FillPowerCapabilities(PNDIS_PNP_CAPABILITIES pCaps)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 ***********************************************************/
ParaNdis_OnOidSetMulticastList(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)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 ***********************************************************/
ParaNdis_OidQueryCopy(tOidDesc * pOid,PVOID pInfo,ULONG ulSize,BOOLEAN bFreeInfo)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 ***********************************************************/
ParaNdis_OidQueryCommon(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)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 ***********************************************************/
ParaNdis_OidName(NDIS_OID oid)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 ***********************************************************/
ValidateWakeupPattern(PNDIS_PM_PACKET_PATTERN p,PULONG pValidSize)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 ***********************************************************/
ParaNdis_OnAddWakeupPattern(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)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 ***********************************************************/
ParaNdis_OnRemoveWakeupPattern(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)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 ***********************************************************/
ParaNdis_OnEnableWakeup(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)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 ***********************************************************/
ParaNdis_OnSetLookahead(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)640 NDIS_STATUS ParaNdis_OnSetLookahead(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
641 {
642 return ParaNdis_OidSetCopy(pOid, &pContext->DummyLookAhead, sizeof(pContext->DummyLookAhead));
643 }
644
ParaNdis_OnSetVlanId(PARANDIS_ADAPTER * pContext,tOidDesc * pOid)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 ***********************************************************/
ParaNdis_GetOidSupportRules(NDIS_OID oid,tOidWhatToDo * pRule,const tOidWhatToDo * Table)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