3 * Copyright (c) 2009, Microsoft Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
26 #include <linux/kernel.h>
27 #include "include/logging.h"
29 #include "include/NetVscApi.h"
30 #include "RndisFilter.h"
36 typedef struct _RNDIS_FILTER_DRIVER_OBJECT
{
37 // The original driver
38 NETVSC_DRIVER_OBJECT InnerDriver
;
40 } RNDIS_FILTER_DRIVER_OBJECT
;
43 RNDIS_DEV_UNINITIALIZED
= 0,
44 RNDIS_DEV_INITIALIZING
,
45 RNDIS_DEV_INITIALIZED
,
46 RNDIS_DEV_DATAINITIALIZED
,
49 typedef struct _RNDIS_DEVICE
{
50 NETVSC_DEVICE
*NetDevice
;
52 RNDIS_DEVICE_STATE State
;
57 LIST_ENTRY RequestList
;
59 unsigned char HwMacAddr
[HW_MACADDR_LEN
];
63 typedef struct _RNDIS_REQUEST
{
67 // FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response,
68 // we can either define a max response message or add a response buffer variable above this field
69 RNDIS_MESSAGE ResponseMessage
;
71 // Simplify allocation by having a netvsc packet inline
74 // FIXME: We assumed a fixed size request here.
75 RNDIS_MESSAGE RequestMessage
;
79 typedef struct _RNDIS_FILTER_PACKET
{
80 void *CompletionContext
;
81 PFN_ON_SENDRECVCOMPLETION OnCompletion
;
83 RNDIS_MESSAGE Message
;
84 } RNDIS_FILTER_PACKET
;
90 RndisFilterSendRequest(
92 RNDIS_REQUEST
*Request
96 RndisFilterReceiveResponse(
98 RNDIS_MESSAGE
*Response
102 RndisFilterReceiveIndicateStatus(
103 RNDIS_DEVICE
*Device
,
104 RNDIS_MESSAGE
*Response
108 RndisFilterReceiveData(
109 RNDIS_DEVICE
*Device
,
110 RNDIS_MESSAGE
*Message
,
111 NETVSC_PACKET
*Packet
115 RndisFilterOnReceive(
116 DEVICE_OBJECT
*Device
,
117 NETVSC_PACKET
*Packet
121 RndisFilterQueryDevice(
122 RNDIS_DEVICE
*Device
,
129 RndisFilterQueryDeviceMac(
134 RndisFilterQueryDeviceLinkStatus(
139 RndisFilterSetPacketFilter(
140 RNDIS_DEVICE
*Device
,
145 RndisFilterInitDevice(
150 RndisFilterOpenDevice(
155 RndisFilterCloseDevice(
160 RndisFilterOnDeviceAdd(
161 DEVICE_OBJECT
*Device
,
166 RndisFilterOnDeviceRemove(
167 DEVICE_OBJECT
*Device
171 RndisFilterOnCleanup(
172 DRIVER_OBJECT
*Driver
177 DEVICE_OBJECT
*Device
182 DEVICE_OBJECT
*Device
187 DEVICE_OBJECT
*Device
,
188 NETVSC_PACKET
*Packet
192 RndisFilterOnSendCompletion(
197 RndisFilterOnSendRequestCompletion(
206 RNDIS_FILTER_DRIVER_OBJECT gRndisFilter
;
208 static inline RNDIS_DEVICE
* GetRndisDevice(void)
210 RNDIS_DEVICE
*device
;
212 device
= MemAllocZeroed(sizeof(RNDIS_DEVICE
));
218 device
->RequestLock
= SpinlockCreate();
219 if (!device
->RequestLock
)
225 INITIALIZE_LIST_HEAD(&device
->RequestList
);
227 device
->State
= RNDIS_DEV_UNINITIALIZED
;
232 static inline void PutRndisDevice(RNDIS_DEVICE
*Device
)
234 SpinlockClose(Device
->RequestLock
);
238 static inline RNDIS_REQUEST
* GetRndisRequest(RNDIS_DEVICE
*Device
, u32 MessageType
, u32 MessageLength
)
240 RNDIS_REQUEST
*request
;
241 RNDIS_MESSAGE
*rndisMessage
;
242 RNDIS_SET_REQUEST
*set
;
244 request
= MemAllocZeroed(sizeof(RNDIS_REQUEST
));
250 request
->WaitEvent
= WaitEventCreate();
251 if (!request
->WaitEvent
)
257 rndisMessage
= &request
->RequestMessage
;
258 rndisMessage
->NdisMessageType
= MessageType
;
259 rndisMessage
->MessageLength
= MessageLength
;
261 // Set the request id. This field is always after the rndis header for request/response packet types so
262 // we just used the SetRequest as a template
263 set
= &rndisMessage
->Message
.SetRequest
;
264 set
->RequestId
= InterlockedIncrement((int*)&Device
->NewRequestId
);
266 // Add to the request list
267 SpinlockAcquire(Device
->RequestLock
);
268 INSERT_TAIL_LIST(&Device
->RequestList
, &request
->ListEntry
);
269 SpinlockRelease(Device
->RequestLock
);
274 static inline void PutRndisRequest(RNDIS_DEVICE
*Device
, RNDIS_REQUEST
*Request
)
276 SpinlockAcquire(Device
->RequestLock
);
277 REMOVE_ENTRY_LIST(&Request
->ListEntry
);
278 SpinlockRelease(Device
->RequestLock
);
280 WaitEventClose(Request
->WaitEvent
);
284 static inline void DumpRndisMessage(RNDIS_MESSAGE
*RndisMessage
)
286 switch (RndisMessage
->NdisMessageType
)
288 case REMOTE_NDIS_PACKET_MSG
:
289 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_PACKET_MSG (len %u, data offset %u data len %u, # oob %u, oob offset %u, oob len %u, pkt offset %u, pkt len %u",
290 RndisMessage
->MessageLength
,
291 RndisMessage
->Message
.Packet
.DataOffset
,
292 RndisMessage
->Message
.Packet
.DataLength
,
293 RndisMessage
->Message
.Packet
.NumOOBDataElements
,
294 RndisMessage
->Message
.Packet
.OOBDataOffset
,
295 RndisMessage
->Message
.Packet
.OOBDataLength
,
296 RndisMessage
->Message
.Packet
.PerPacketInfoOffset
,
297 RndisMessage
->Message
.Packet
.PerPacketInfoLength
);
300 case REMOTE_NDIS_INITIALIZE_CMPLT
:
301 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_INITIALIZE_CMPLT (len %u, id 0x%x, status 0x%x, major %d, minor %d, device flags %d, max xfer size 0x%x, max pkts %u, pkt aligned %u)",
302 RndisMessage
->MessageLength
,
303 RndisMessage
->Message
.InitializeComplete
.RequestId
,
304 RndisMessage
->Message
.InitializeComplete
.Status
,
305 RndisMessage
->Message
.InitializeComplete
.MajorVersion
,
306 RndisMessage
->Message
.InitializeComplete
.MinorVersion
,
307 RndisMessage
->Message
.InitializeComplete
.DeviceFlags
,
308 RndisMessage
->Message
.InitializeComplete
.MaxTransferSize
,
309 RndisMessage
->Message
.InitializeComplete
.MaxPacketsPerMessage
,
310 RndisMessage
->Message
.InitializeComplete
.PacketAlignmentFactor
);
313 case REMOTE_NDIS_QUERY_CMPLT
:
314 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_QUERY_CMPLT (len %u, id 0x%x, status 0x%x, buf len %u, buf offset %u)",
315 RndisMessage
->MessageLength
,
316 RndisMessage
->Message
.QueryComplete
.RequestId
,
317 RndisMessage
->Message
.QueryComplete
.Status
,
318 RndisMessage
->Message
.QueryComplete
.InformationBufferLength
,
319 RndisMessage
->Message
.QueryComplete
.InformationBufferOffset
);
322 case REMOTE_NDIS_SET_CMPLT
:
323 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
324 RndisMessage
->MessageLength
,
325 RndisMessage
->Message
.SetComplete
.RequestId
,
326 RndisMessage
->Message
.SetComplete
.Status
);
329 case REMOTE_NDIS_INDICATE_STATUS_MSG
:
330 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_INDICATE_STATUS_MSG (len %u, status 0x%x, buf len %u, buf offset %u)",
331 RndisMessage
->MessageLength
,
332 RndisMessage
->Message
.IndicateStatus
.Status
,
333 RndisMessage
->Message
.IndicateStatus
.StatusBufferLength
,
334 RndisMessage
->Message
.IndicateStatus
.StatusBufferOffset
);
338 DPRINT_DBG(NETVSC
, "0x%x (len %u)",
339 RndisMessage
->NdisMessageType
,
340 RndisMessage
->MessageLength
);
346 RndisFilterSendRequest(
347 RNDIS_DEVICE
*Device
,
348 RNDIS_REQUEST
*Request
352 NETVSC_PACKET
*packet
;
354 DPRINT_ENTER(NETVSC
);
356 // Setup the packet to send it
357 packet
= &Request
->Packet
;
359 packet
->IsDataPacket
= FALSE
;
360 packet
->TotalDataBufferLength
= Request
->RequestMessage
.MessageLength
;
361 packet
->PageBufferCount
= 1;
363 packet
->PageBuffers
[0].Pfn
= GetPhysicalAddress(&Request
->RequestMessage
) >> PAGE_SHIFT
;
364 packet
->PageBuffers
[0].Length
= Request
->RequestMessage
.MessageLength
;
365 packet
->PageBuffers
[0].Offset
= (ULONG_PTR
)&Request
->RequestMessage
& (PAGE_SIZE
-1);
367 packet
->Completion
.Send
.SendCompletionContext
= Request
;//packet;
368 packet
->Completion
.Send
.OnSendCompletion
= RndisFilterOnSendRequestCompletion
;
369 packet
->Completion
.Send
.SendCompletionTid
= (ULONG_PTR
)Device
;
371 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
->NetDevice
->Device
, packet
);
378 RndisFilterReceiveResponse(
379 RNDIS_DEVICE
*Device
,
380 RNDIS_MESSAGE
*Response
385 RNDIS_REQUEST
*request
=NULL
;
388 DPRINT_ENTER(NETVSC
);
390 SpinlockAcquire(Device
->RequestLock
);
391 ITERATE_LIST_ENTRIES(anchor
, curr
, &Device
->RequestList
)
393 request
= CONTAINING_RECORD(curr
, RNDIS_REQUEST
, ListEntry
);
395 // All request/response message contains RequestId as the 1st field
396 if (request
->RequestMessage
.Message
.InitializeRequest
.RequestId
== Response
->Message
.InitializeComplete
.RequestId
)
398 DPRINT_DBG(NETVSC
, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
399 request
->RequestMessage
.Message
.InitializeRequest
.RequestId
, request
->RequestMessage
.NdisMessageType
, Response
->NdisMessageType
);
405 SpinlockRelease(Device
->RequestLock
);
409 if (Response
->MessageLength
<= sizeof(RNDIS_MESSAGE
))
411 memcpy(&request
->ResponseMessage
, Response
, Response
->MessageLength
);
415 DPRINT_ERR(NETVSC
, "rndis response buffer overflow detected (size %u max %u)", Response
->MessageLength
, sizeof(RNDIS_FILTER_PACKET
));
417 if (Response
->NdisMessageType
== REMOTE_NDIS_RESET_CMPLT
) // does not have a request id field
419 request
->ResponseMessage
.Message
.ResetComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
423 request
->ResponseMessage
.Message
.InitializeComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
427 WaitEventSet(request
->WaitEvent
);
431 DPRINT_ERR(NETVSC
, "no rndis request found for this response (id 0x%x res type 0x%x)",
432 Response
->Message
.InitializeComplete
.RequestId
, Response
->NdisMessageType
);
439 RndisFilterReceiveIndicateStatus(
440 RNDIS_DEVICE
*Device
,
441 RNDIS_MESSAGE
*Response
444 RNDIS_INDICATE_STATUS
*indicate
= &Response
->Message
.IndicateStatus
;
446 if (indicate
->Status
== RNDIS_STATUS_MEDIA_CONNECT
)
448 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 1);
450 else if (indicate
->Status
== RNDIS_STATUS_MEDIA_DISCONNECT
)
452 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 0);
461 RndisFilterReceiveData(
462 RNDIS_DEVICE
*Device
,
463 RNDIS_MESSAGE
*Message
,
464 NETVSC_PACKET
*Packet
467 RNDIS_PACKET
*rndisPacket
;
470 DPRINT_ENTER(NETVSC
);
472 // empty ethernet frame ??
473 ASSERT(Packet
->PageBuffers
[0].Length
> RNDIS_MESSAGE_SIZE(RNDIS_PACKET
));
475 rndisPacket
= &Message
->Message
.Packet
;
477 // FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
478 // netvsc packet (ie TotalDataBufferLength != MessageLength)
480 // Remove the rndis header and pass it back up the stack
481 dataOffset
= RNDIS_HEADER_SIZE
+ rndisPacket
->DataOffset
;
483 Packet
->TotalDataBufferLength
-= dataOffset
;
484 Packet
->PageBuffers
[0].Offset
+= dataOffset
;
485 Packet
->PageBuffers
[0].Length
-= dataOffset
;
487 Packet
->IsDataPacket
= TRUE
;
489 gRndisFilter
.InnerDriver
.OnReceiveCallback(Device
->NetDevice
->Device
, Packet
);
495 RndisFilterOnReceive(
496 DEVICE_OBJECT
*Device
,
497 NETVSC_PACKET
*Packet
500 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
501 RNDIS_DEVICE
*rndisDevice
;
502 RNDIS_MESSAGE rndisMessage
;
503 RNDIS_MESSAGE
*rndisHeader
;
505 DPRINT_ENTER(NETVSC
);
508 //Make sure the rndis device state is initialized
509 if (!netDevice
->Extension
)
511 DPRINT_ERR(NETVSC
, "got rndis message but no rndis device...dropping this message!");
516 rndisDevice
= (RNDIS_DEVICE
*)netDevice
->Extension
;
517 if (rndisDevice
->State
== RNDIS_DEV_UNINITIALIZED
)
519 DPRINT_ERR(NETVSC
, "got rndis message but rndis device uninitialized...dropping this message!");
524 rndisHeader
= (RNDIS_MESSAGE
*)PageMapVirtualAddress(Packet
->PageBuffers
[0].Pfn
);
526 rndisHeader
= (void*)((ULONG_PTR
)rndisHeader
+ Packet
->PageBuffers
[0].Offset
);
528 // Make sure we got a valid rndis message
529 // FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but
530 // the ByteCount field in the xfer page range shows 52 bytes
532 if ( Packet
->TotalDataBufferLength
!= rndisHeader
->MessageLength
)
534 PageUnmapVirtualAddress((void*)(ULONG_PTR
)rndisHeader
- Packet
->PageBuffers
[0].Offset
);
536 DPRINT_ERR(NETVSC
, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
537 rndisHeader
->MessageLength
, Packet
->TotalDataBufferLength
);
543 if ((rndisHeader
->NdisMessageType
!= REMOTE_NDIS_PACKET_MSG
) && (rndisHeader
->MessageLength
> sizeof(RNDIS_MESSAGE
)))
545 DPRINT_ERR(NETVSC
, "incoming rndis message buffer overflow detected (got %u, max %u)...marking it an error!",
546 rndisHeader
->MessageLength
, sizeof(RNDIS_MESSAGE
));
549 memcpy(&rndisMessage
, rndisHeader
, (rndisHeader
->MessageLength
> sizeof(RNDIS_MESSAGE
))?sizeof(RNDIS_MESSAGE
):rndisHeader
->MessageLength
);
551 PageUnmapVirtualAddress((void*)(ULONG_PTR
)rndisHeader
- Packet
->PageBuffers
[0].Offset
);
553 DumpRndisMessage(&rndisMessage
);
555 switch (rndisMessage
.NdisMessageType
)
558 case REMOTE_NDIS_PACKET_MSG
:
559 RndisFilterReceiveData(rndisDevice
, &rndisMessage
, Packet
);
563 case REMOTE_NDIS_INITIALIZE_CMPLT
:
564 case REMOTE_NDIS_QUERY_CMPLT
:
565 case REMOTE_NDIS_SET_CMPLT
:
566 //case REMOTE_NDIS_RESET_CMPLT:
567 //case REMOTE_NDIS_KEEPALIVE_CMPLT:
568 RndisFilterReceiveResponse(rndisDevice
, &rndisMessage
);
572 case REMOTE_NDIS_INDICATE_STATUS_MSG
:
573 RndisFilterReceiveIndicateStatus(rndisDevice
, &rndisMessage
);
576 DPRINT_ERR(NETVSC
, "unhandled rndis message (type %u len %u)", rndisMessage
.NdisMessageType
, rndisMessage
.MessageLength
);
586 RndisFilterQueryDevice(
587 RNDIS_DEVICE
*Device
,
593 RNDIS_REQUEST
*request
;
594 u32 inresultSize
= *ResultSize
;
595 RNDIS_QUERY_REQUEST
*query
;
596 RNDIS_QUERY_COMPLETE
*queryComplete
;
599 DPRINT_ENTER(NETVSC
);
604 request
= GetRndisRequest(Device
, REMOTE_NDIS_QUERY_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST
));
611 // Setup the rndis query
612 query
= &request
->RequestMessage
.Message
.QueryRequest
;
614 query
->InformationBufferOffset
= sizeof(RNDIS_QUERY_REQUEST
);
615 query
->InformationBufferLength
= 0;
616 query
->DeviceVcHandle
= 0;
618 ret
= RndisFilterSendRequest(Device
, request
);
624 WaitEventWait(request
->WaitEvent
);
626 // Copy the response back
627 queryComplete
= &request
->ResponseMessage
.Message
.QueryComplete
;
629 if (queryComplete
->InformationBufferLength
> inresultSize
)
636 (void*)((ULONG_PTR
)queryComplete
+ queryComplete
->InformationBufferOffset
),
637 queryComplete
->InformationBufferLength
);
639 *ResultSize
= queryComplete
->InformationBufferLength
;
644 PutRndisRequest(Device
, request
);
652 RndisFilterQueryDeviceMac(
656 u32 size
=HW_MACADDR_LEN
;
658 return RndisFilterQueryDevice(Device
,
659 RNDIS_OID_802_3_PERMANENT_ADDRESS
,
665 RndisFilterQueryDeviceLinkStatus(
669 u32 size
=sizeof(u32
);
671 return RndisFilterQueryDevice(Device
,
672 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS
,
678 RndisFilterSetPacketFilter(
679 RNDIS_DEVICE
*Device
,
683 RNDIS_REQUEST
*request
;
684 RNDIS_SET_REQUEST
*set
;
685 RNDIS_SET_COMPLETE
*setComplete
;
689 DPRINT_ENTER(NETVSC
);
691 ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST
) + sizeof(u32
) <= sizeof(RNDIS_MESSAGE
));
693 request
= GetRndisRequest(Device
, REMOTE_NDIS_SET_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST
) + sizeof(u32
));
700 // Setup the rndis set
701 set
= &request
->RequestMessage
.Message
.SetRequest
;
702 set
->Oid
= RNDIS_OID_GEN_CURRENT_PACKET_FILTER
;
703 set
->InformationBufferLength
= sizeof(u32
);
704 set
->InformationBufferOffset
= sizeof(RNDIS_SET_REQUEST
);
706 memcpy((void*)(ULONG_PTR
)set
+ sizeof(RNDIS_SET_REQUEST
), &NewFilter
, sizeof(u32
));
708 ret
= RndisFilterSendRequest(Device
, request
);
714 ret
= WaitEventWaitEx(request
->WaitEvent
, 2000/*2sec*/);
718 DPRINT_ERR(NETVSC
, "timeout before we got a set response...");
719 // We cant deallocate the request since we may still receive a send completion for it.
728 setComplete
= &request
->ResponseMessage
.Message
.SetComplete
;
729 status
= setComplete
->Status
;
735 PutRndisRequest(Device
, request
);
745 NETVSC_DRIVER_OBJECT
*Driver
748 DPRINT_ENTER(NETVSC
);
750 DPRINT_DBG(NETVSC
, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET
));
752 Driver
->RequestExtSize
= sizeof(RNDIS_FILTER_PACKET
);
753 Driver
->AdditionalRequestPageBufferCount
= 1; // For rndis header
755 //Driver->Context = rndisDriver;
757 memset(&gRndisFilter
, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT
));
759 /*rndisDriver->Driver = Driver;
761 ASSERT(Driver->OnLinkStatusChanged);
762 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
764 // Save the original dispatch handlers before we override it
765 gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd
= Driver
->Base
.OnDeviceAdd
;
766 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove
= Driver
->Base
.OnDeviceRemove
;
767 gRndisFilter
.InnerDriver
.Base
.OnCleanup
= Driver
->Base
.OnCleanup
;
769 ASSERT(Driver
->OnSend
);
770 ASSERT(Driver
->OnReceiveCallback
);
771 gRndisFilter
.InnerDriver
.OnSend
= Driver
->OnSend
;
772 gRndisFilter
.InnerDriver
.OnReceiveCallback
= Driver
->OnReceiveCallback
;
773 gRndisFilter
.InnerDriver
.OnLinkStatusChanged
= Driver
->OnLinkStatusChanged
;
776 Driver
->Base
.OnDeviceAdd
= RndisFilterOnDeviceAdd
;
777 Driver
->Base
.OnDeviceRemove
= RndisFilterOnDeviceRemove
;
778 Driver
->Base
.OnCleanup
= RndisFilterOnCleanup
;
779 Driver
->OnSend
= RndisFilterOnSend
;
780 Driver
->OnOpen
= RndisFilterOnOpen
;
781 Driver
->OnClose
= RndisFilterOnClose
;
782 //Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus;
783 Driver
->OnReceiveCallback
= RndisFilterOnReceive
;
791 RndisFilterInitDevice(
795 RNDIS_REQUEST
*request
;
796 RNDIS_INITIALIZE_REQUEST
*init
;
797 RNDIS_INITIALIZE_COMPLETE
*initComplete
;
801 DPRINT_ENTER(NETVSC
);
803 request
= GetRndisRequest(Device
, REMOTE_NDIS_INITIALIZE_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST
));
810 // Setup the rndis set
811 init
= &request
->RequestMessage
.Message
.InitializeRequest
;
812 init
->MajorVersion
= RNDIS_MAJOR_VERSION
;
813 init
->MinorVersion
= RNDIS_MINOR_VERSION
;
814 init
->MaxTransferSize
= 2048; // FIXME: Use 1536 - rounded ethernet frame size
816 Device
->State
= RNDIS_DEV_INITIALIZING
;
818 ret
= RndisFilterSendRequest(Device
, request
);
821 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
825 WaitEventWait(request
->WaitEvent
);
827 initComplete
= &request
->ResponseMessage
.Message
.InitializeComplete
;
828 status
= initComplete
->Status
;
829 if (status
== RNDIS_STATUS_SUCCESS
)
831 Device
->State
= RNDIS_DEV_INITIALIZED
;
836 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
843 PutRndisRequest(Device
, request
);
851 RndisFilterHaltDevice(
855 RNDIS_REQUEST
*request
;
856 RNDIS_HALT_REQUEST
*halt
;
858 DPRINT_ENTER(NETVSC
);
860 // Attempt to do a rndis device halt
861 request
= GetRndisRequest(Device
, REMOTE_NDIS_HALT_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST
));
867 // Setup the rndis set
868 halt
= &request
->RequestMessage
.Message
.HaltRequest
;
869 halt
->RequestId
= InterlockedIncrement((int*)&Device
->NewRequestId
);
871 // Ignore return since this msg is optional.
872 RndisFilterSendRequest(Device
, request
);
874 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
879 PutRndisRequest(Device
, request
);
887 RndisFilterOpenDevice(
893 DPRINT_ENTER(NETVSC
);
895 if (Device
->State
!= RNDIS_DEV_INITIALIZED
)
898 ret
= RndisFilterSetPacketFilter(Device
, NDIS_PACKET_TYPE_BROADCAST
|NDIS_PACKET_TYPE_DIRECTED
);
901 Device
->State
= RNDIS_DEV_DATAINITIALIZED
;
909 RndisFilterCloseDevice(
915 DPRINT_ENTER(NETVSC
);
917 if (Device
->State
!= RNDIS_DEV_DATAINITIALIZED
)
920 ret
= RndisFilterSetPacketFilter(Device
, 0);
923 Device
->State
= RNDIS_DEV_INITIALIZED
;
933 RndisFilterOnDeviceAdd(
934 DEVICE_OBJECT
*Device
,
939 NETVSC_DEVICE
*netDevice
;
940 RNDIS_DEVICE
*rndisDevice
;
941 NETVSC_DEVICE_INFO
*deviceInfo
= (NETVSC_DEVICE_INFO
*)AdditionalInfo
;
943 DPRINT_ENTER(NETVSC
);
945 //rndisDevice = MemAlloc(sizeof(RNDIS_DEVICE));
946 rndisDevice
= GetRndisDevice();
953 DPRINT_DBG(NETVSC
, "rndis device object allocated - %p", rndisDevice
);
955 // Let the inner driver handle this first to create the netvsc channel
956 // NOTE! Once the channel is created, we may get a receive callback
957 // (RndisFilterOnReceive()) before this call is completed
958 ret
= gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd(Device
, AdditionalInfo
);
961 PutRndisDevice(rndisDevice
);
967 // Initialize the rndis device
969 netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
971 ASSERT(netDevice
->Device
);
973 netDevice
->Extension
= rndisDevice
;
974 rndisDevice
->NetDevice
= netDevice
;
976 // Send the rndis initialization message
977 ret
= RndisFilterInitDevice(rndisDevice
);
980 // TODO: If rndis init failed, we will need to shut down the channel
983 // Get the mac address
984 ret
= RndisFilterQueryDeviceMac(rndisDevice
);
987 // TODO: shutdown rndis device and the channel
990 DPRINT_INFO(NETVSC
, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
992 rndisDevice
->HwMacAddr
[0],
993 rndisDevice
->HwMacAddr
[1],
994 rndisDevice
->HwMacAddr
[2],
995 rndisDevice
->HwMacAddr
[3],
996 rndisDevice
->HwMacAddr
[4],
997 rndisDevice
->HwMacAddr
[5]);
999 memcpy(deviceInfo
->MacAddr
, rndisDevice
->HwMacAddr
, HW_MACADDR_LEN
);
1001 RndisFilterQueryDeviceLinkStatus(rndisDevice
);
1003 deviceInfo
->LinkState
= rndisDevice
->LinkStatus
;
1004 DPRINT_INFO(NETVSC
, "Device 0x%p link state %s", rndisDevice
, ((deviceInfo
->LinkState
)?("down"):("up")));
1006 DPRINT_EXIT(NETVSC
);
1013 RndisFilterOnDeviceRemove(
1014 DEVICE_OBJECT
*Device
1017 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
1018 RNDIS_DEVICE
*rndisDevice
= (RNDIS_DEVICE
*)netDevice
->Extension
;
1020 DPRINT_ENTER(NETVSC
);
1022 // Halt and release the rndis device
1023 RndisFilterHaltDevice(rndisDevice
);
1025 PutRndisDevice(rndisDevice
);
1026 netDevice
->Extension
= NULL
;
1028 // Pass control to inner driver to remove the device
1029 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove(Device
);
1031 DPRINT_EXIT(NETVSC
);
1038 RndisFilterOnCleanup(
1039 DRIVER_OBJECT
*Driver
1042 DPRINT_ENTER(NETVSC
);
1044 DPRINT_EXIT(NETVSC
);
1049 DEVICE_OBJECT
*Device
1053 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
1055 DPRINT_ENTER(NETVSC
);
1058 ret
= RndisFilterOpenDevice((RNDIS_DEVICE
*)netDevice
->Extension
);
1060 DPRINT_EXIT(NETVSC
);
1067 DEVICE_OBJECT
*Device
1071 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
1073 DPRINT_ENTER(NETVSC
);
1076 ret
= RndisFilterCloseDevice((RNDIS_DEVICE
*)netDevice
->Extension
);
1078 DPRINT_EXIT(NETVSC
);
1086 DEVICE_OBJECT
*Device
,
1087 NETVSC_PACKET
*Packet
1091 RNDIS_FILTER_PACKET
*filterPacket
;
1092 RNDIS_MESSAGE
*rndisMessage
;
1093 RNDIS_PACKET
*rndisPacket
;
1094 u32 rndisMessageSize
;
1096 DPRINT_ENTER(NETVSC
);
1098 // Add the rndis header
1099 filterPacket
= (RNDIS_FILTER_PACKET
*)Packet
->Extension
;
1100 ASSERT(filterPacket
);
1102 memset(filterPacket
, 0, sizeof(RNDIS_FILTER_PACKET
));
1104 rndisMessage
= &filterPacket
->Message
;
1105 rndisMessageSize
= RNDIS_MESSAGE_SIZE(RNDIS_PACKET
);
1107 rndisMessage
->NdisMessageType
= REMOTE_NDIS_PACKET_MSG
;
1108 rndisMessage
->MessageLength
= Packet
->TotalDataBufferLength
+ rndisMessageSize
;
1110 rndisPacket
= &rndisMessage
->Message
.Packet
;
1111 rndisPacket
->DataOffset
= sizeof(RNDIS_PACKET
);
1112 rndisPacket
->DataLength
= Packet
->TotalDataBufferLength
;
1114 Packet
->IsDataPacket
= TRUE
;
1115 Packet
->PageBuffers
[0].Pfn
= GetPhysicalAddress(rndisMessage
) >> PAGE_SHIFT
;
1116 Packet
->PageBuffers
[0].Offset
= (ULONG_PTR
)rndisMessage
& (PAGE_SIZE
-1);
1117 Packet
->PageBuffers
[0].Length
= rndisMessageSize
;
1119 // Save the packet send completion and context
1120 filterPacket
->OnCompletion
= Packet
->Completion
.Send
.OnSendCompletion
;
1121 filterPacket
->CompletionContext
= Packet
->Completion
.Send
.SendCompletionContext
;
1124 Packet
->Completion
.Send
.OnSendCompletion
= RndisFilterOnSendCompletion
;
1125 Packet
->Completion
.Send
.SendCompletionContext
= filterPacket
;
1127 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
, Packet
);
1130 // Reset the completion to originals to allow retries from above
1131 Packet
->Completion
.Send
.OnSendCompletion
= filterPacket
->OnCompletion
;
1132 Packet
->Completion
.Send
.SendCompletionContext
= filterPacket
->CompletionContext
;
1135 DPRINT_EXIT(NETVSC
);
1141 RndisFilterOnSendCompletion(
1144 RNDIS_FILTER_PACKET
*filterPacket
= (RNDIS_FILTER_PACKET
*)Context
;
1146 DPRINT_ENTER(NETVSC
);
1148 // Pass it back to the original handler
1149 filterPacket
->OnCompletion(filterPacket
->CompletionContext
);
1151 DPRINT_EXIT(NETVSC
);
1156 RndisFilterOnSendRequestCompletion(
1160 DPRINT_ENTER(NETVSC
);
1163 DPRINT_EXIT(NETVSC
);