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