Staging: hv: remove UINT64 and INT64 and UCHAR typedefs
[deliverable/linux.git] / drivers / staging / hv / RndisFilter.c
1 /*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
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.
8 *
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
12 * more details.
13 *
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.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 *
22 */
23
24 #define KERNEL_2_6_27
25
26 #include <linux/kernel.h>
27 #include "include/logging.h"
28
29 #include "include/NetVscApi.h"
30 #include "RndisFilter.h"
31
32 //
33 // Data types
34 //
35
36 typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
37 // The original driver
38 NETVSC_DRIVER_OBJECT InnerDriver;
39
40 } RNDIS_FILTER_DRIVER_OBJECT;
41
42 typedef enum {
43 RNDIS_DEV_UNINITIALIZED = 0,
44 RNDIS_DEV_INITIALIZING,
45 RNDIS_DEV_INITIALIZED,
46 RNDIS_DEV_DATAINITIALIZED,
47 } RNDIS_DEVICE_STATE;
48
49 typedef struct _RNDIS_DEVICE {
50 NETVSC_DEVICE *NetDevice;
51
52 RNDIS_DEVICE_STATE State;
53 u32 LinkStatus;
54 u32 NewRequestId;
55
56 HANDLE RequestLock;
57 LIST_ENTRY RequestList;
58
59 unsigned char HwMacAddr[HW_MACADDR_LEN];
60 } RNDIS_DEVICE;
61
62
63 typedef struct _RNDIS_REQUEST {
64 LIST_ENTRY ListEntry;
65 HANDLE WaitEvent;
66
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;
70
71 // Simplify allocation by having a netvsc packet inline
72 NETVSC_PACKET Packet;
73 PAGE_BUFFER Buffer;
74 // FIXME: We assumed a fixed size request here.
75 RNDIS_MESSAGE RequestMessage;
76 } RNDIS_REQUEST;
77
78
79 typedef struct _RNDIS_FILTER_PACKET {
80 void *CompletionContext;
81 PFN_ON_SENDRECVCOMPLETION OnCompletion;
82
83 RNDIS_MESSAGE Message;
84 } RNDIS_FILTER_PACKET;
85
86 //
87 // Internal routines
88 //
89 static int
90 RndisFilterSendRequest(
91 RNDIS_DEVICE *Device,
92 RNDIS_REQUEST *Request
93 );
94
95 static void
96 RndisFilterReceiveResponse(
97 RNDIS_DEVICE *Device,
98 RNDIS_MESSAGE *Response
99 );
100
101 static void
102 RndisFilterReceiveIndicateStatus(
103 RNDIS_DEVICE *Device,
104 RNDIS_MESSAGE *Response
105 );
106
107 static void
108 RndisFilterReceiveData(
109 RNDIS_DEVICE *Device,
110 RNDIS_MESSAGE *Message,
111 NETVSC_PACKET *Packet
112 );
113
114 static int
115 RndisFilterOnReceive(
116 DEVICE_OBJECT *Device,
117 NETVSC_PACKET *Packet
118 );
119
120 static int
121 RndisFilterQueryDevice(
122 RNDIS_DEVICE *Device,
123 u32 Oid,
124 void *Result,
125 u32 *ResultSize
126 );
127
128 static inline int
129 RndisFilterQueryDeviceMac(
130 RNDIS_DEVICE *Device
131 );
132
133 static inline int
134 RndisFilterQueryDeviceLinkStatus(
135 RNDIS_DEVICE *Device
136 );
137
138 static int
139 RndisFilterSetPacketFilter(
140 RNDIS_DEVICE *Device,
141 u32 NewFilter
142 );
143
144 static int
145 RndisFilterInitDevice(
146 RNDIS_DEVICE *Device
147 );
148
149 static int
150 RndisFilterOpenDevice(
151 RNDIS_DEVICE *Device
152 );
153
154 static int
155 RndisFilterCloseDevice(
156 RNDIS_DEVICE *Device
157 );
158
159 static int
160 RndisFilterOnDeviceAdd(
161 DEVICE_OBJECT *Device,
162 void *AdditionalInfo
163 );
164
165 static int
166 RndisFilterOnDeviceRemove(
167 DEVICE_OBJECT *Device
168 );
169
170 static void
171 RndisFilterOnCleanup(
172 DRIVER_OBJECT *Driver
173 );
174
175 static int
176 RndisFilterOnOpen(
177 DEVICE_OBJECT *Device
178 );
179
180 static int
181 RndisFilterOnClose(
182 DEVICE_OBJECT *Device
183 );
184
185 static int
186 RndisFilterOnSend(
187 DEVICE_OBJECT *Device,
188 NETVSC_PACKET *Packet
189 );
190
191 static void
192 RndisFilterOnSendCompletion(
193 void *Context
194 );
195
196 static void
197 RndisFilterOnSendRequestCompletion(
198 void *Context
199 );
200
201 //
202 // Global var
203 //
204
205 // The one and only
206 RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
207
208 static inline RNDIS_DEVICE* GetRndisDevice(void)
209 {
210 RNDIS_DEVICE *device;
211
212 device = MemAllocZeroed(sizeof(RNDIS_DEVICE));
213 if (!device)
214 {
215 return NULL;
216 }
217
218 device->RequestLock = SpinlockCreate();
219 if (!device->RequestLock)
220 {
221 MemFree(device);
222 return NULL;
223 }
224
225 INITIALIZE_LIST_HEAD(&device->RequestList);
226
227 device->State = RNDIS_DEV_UNINITIALIZED;
228
229 return device;
230 }
231
232 static inline void PutRndisDevice(RNDIS_DEVICE *Device)
233 {
234 SpinlockClose(Device->RequestLock);
235 MemFree(Device);
236 }
237
238 static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, u32 MessageType, u32 MessageLength)
239 {
240 RNDIS_REQUEST *request;
241 RNDIS_MESSAGE *rndisMessage;
242 RNDIS_SET_REQUEST *set;
243
244 request = MemAllocZeroed(sizeof(RNDIS_REQUEST));
245 if (!request)
246 {
247 return NULL;
248 }
249
250 request->WaitEvent = WaitEventCreate();
251 if (!request->WaitEvent)
252 {
253 MemFree(request);
254 return NULL;
255 }
256
257 rndisMessage = &request->RequestMessage;
258 rndisMessage->NdisMessageType = MessageType;
259 rndisMessage->MessageLength = MessageLength;
260
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);
265
266 // Add to the request list
267 SpinlockAcquire(Device->RequestLock);
268 INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
269 SpinlockRelease(Device->RequestLock);
270
271 return request;
272 }
273
274 static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
275 {
276 SpinlockAcquire(Device->RequestLock);
277 REMOVE_ENTRY_LIST(&Request->ListEntry);
278 SpinlockRelease(Device->RequestLock);
279
280 WaitEventClose(Request->WaitEvent);
281 MemFree(Request);
282 }
283
284 static inline void DumpRndisMessage(RNDIS_MESSAGE *RndisMessage)
285 {
286 switch (RndisMessage->NdisMessageType)
287 {
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);
298 break;
299
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);
311 break;
312
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);
320 break;
321
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);
327 break;
328
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);
335 break;
336
337 default:
338 DPRINT_DBG(NETVSC, "0x%x (len %u)",
339 RndisMessage->NdisMessageType,
340 RndisMessage->MessageLength);
341 break;
342 }
343 }
344
345 static int
346 RndisFilterSendRequest(
347 RNDIS_DEVICE *Device,
348 RNDIS_REQUEST *Request
349 )
350 {
351 int ret=0;
352 NETVSC_PACKET *packet;
353
354 DPRINT_ENTER(NETVSC);
355
356 // Setup the packet to send it
357 packet = &Request->Packet;
358
359 packet->IsDataPacket = FALSE;
360 packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
361 packet->PageBufferCount = 1;
362
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);
366
367 packet->Completion.Send.SendCompletionContext = Request;//packet;
368 packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
369 packet->Completion.Send.SendCompletionTid = (ULONG_PTR)Device;
370
371 ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
372 DPRINT_EXIT(NETVSC);
373 return ret;
374 }
375
376
377 static void
378 RndisFilterReceiveResponse(
379 RNDIS_DEVICE *Device,
380 RNDIS_MESSAGE *Response
381 )
382 {
383 LIST_ENTRY *anchor;
384 LIST_ENTRY *curr;
385 RNDIS_REQUEST *request=NULL;
386 BOOL found=FALSE;
387
388 DPRINT_ENTER(NETVSC);
389
390 SpinlockAcquire(Device->RequestLock);
391 ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList)
392 {
393 request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
394
395 // All request/response message contains RequestId as the 1st field
396 if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
397 {
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);
400
401 found = TRUE;
402 break;
403 }
404 }
405 SpinlockRelease(Device->RequestLock);
406
407 if (found)
408 {
409 if (Response->MessageLength <= sizeof(RNDIS_MESSAGE))
410 {
411 memcpy(&request->ResponseMessage, Response, Response->MessageLength);
412 }
413 else
414 {
415 DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %u)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
416
417 if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) // does not have a request id field
418 {
419 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
420 }
421 else
422 {
423 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
424 }
425 }
426
427 WaitEventSet(request->WaitEvent);
428 }
429 else
430 {
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);
433 }
434
435 DPRINT_EXIT(NETVSC);
436 }
437
438 static void
439 RndisFilterReceiveIndicateStatus(
440 RNDIS_DEVICE *Device,
441 RNDIS_MESSAGE *Response
442 )
443 {
444 RNDIS_INDICATE_STATUS *indicate = &Response->Message.IndicateStatus;
445
446 if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT)
447 {
448 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
449 }
450 else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT)
451 {
452 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
453 }
454 else
455 {
456 // TODO:
457 }
458 }
459
460 static void
461 RndisFilterReceiveData(
462 RNDIS_DEVICE *Device,
463 RNDIS_MESSAGE *Message,
464 NETVSC_PACKET *Packet
465 )
466 {
467 RNDIS_PACKET *rndisPacket;
468 u32 dataOffset;
469
470 DPRINT_ENTER(NETVSC);
471
472 // empty ethernet frame ??
473 ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(RNDIS_PACKET));
474
475 rndisPacket = &Message->Message.Packet;
476
477 // FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
478 // netvsc packet (ie TotalDataBufferLength != MessageLength)
479
480 // Remove the rndis header and pass it back up the stack
481 dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
482
483 Packet->TotalDataBufferLength -= dataOffset;
484 Packet->PageBuffers[0].Offset += dataOffset;
485 Packet->PageBuffers[0].Length -= dataOffset;
486
487 Packet->IsDataPacket = TRUE;
488
489 gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device, Packet);
490
491 DPRINT_EXIT(NETVSC);
492 }
493
494 static int
495 RndisFilterOnReceive(
496 DEVICE_OBJECT *Device,
497 NETVSC_PACKET *Packet
498 )
499 {
500 NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
501 RNDIS_DEVICE *rndisDevice;
502 RNDIS_MESSAGE rndisMessage;
503 RNDIS_MESSAGE *rndisHeader;
504
505 DPRINT_ENTER(NETVSC);
506
507 ASSERT(netDevice);
508 //Make sure the rndis device state is initialized
509 if (!netDevice->Extension)
510 {
511 DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
512 DPRINT_EXIT(NETVSC);
513 return -1;
514 }
515
516 rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
517 if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED)
518 {
519 DPRINT_ERR(NETVSC, "got rndis message but rndis device uninitialized...dropping this message!");
520 DPRINT_EXIT(NETVSC);
521 return -1;
522 }
523
524 rndisHeader = (RNDIS_MESSAGE*)PageMapVirtualAddress(Packet->PageBuffers[0].Pfn);
525
526 rndisHeader = (void*)((ULONG_PTR)rndisHeader + Packet->PageBuffers[0].Offset);
527
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
531 #if 0
532 if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
533 {
534 PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
535
536 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
537 rndisHeader->MessageLength, Packet->TotalDataBufferLength);
538 DPRINT_EXIT(NETVSC);
539 return -1;
540 }
541 #endif
542
543 if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE)))
544 {
545 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %u)...marking it an error!",
546 rndisHeader->MessageLength, sizeof(RNDIS_MESSAGE));
547 }
548
549 memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE))?sizeof(RNDIS_MESSAGE):rndisHeader->MessageLength);
550
551 PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
552
553 DumpRndisMessage(&rndisMessage);
554
555 switch (rndisMessage.NdisMessageType)
556 {
557 // data msg
558 case REMOTE_NDIS_PACKET_MSG:
559 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
560 break;
561
562 // completion msgs
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);
569 break;
570
571 // notification msgs
572 case REMOTE_NDIS_INDICATE_STATUS_MSG:
573 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
574 break;
575 default:
576 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", rndisMessage.NdisMessageType, rndisMessage.MessageLength);
577 break;
578 }
579
580 DPRINT_EXIT(NETVSC);
581 return 0;
582 }
583
584
585 static int
586 RndisFilterQueryDevice(
587 RNDIS_DEVICE *Device,
588 u32 Oid,
589 void *Result,
590 u32 *ResultSize
591 )
592 {
593 RNDIS_REQUEST *request;
594 u32 inresultSize = *ResultSize;
595 RNDIS_QUERY_REQUEST *query;
596 RNDIS_QUERY_COMPLETE *queryComplete;
597 int ret=0;
598
599 DPRINT_ENTER(NETVSC);
600
601 ASSERT(Result);
602
603 *ResultSize = 0;
604 request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST));
605 if (!request)
606 {
607 ret = -1;
608 goto Cleanup;
609 }
610
611 // Setup the rndis query
612 query = &request->RequestMessage.Message.QueryRequest;
613 query->Oid = Oid;
614 query->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
615 query->InformationBufferLength = 0;
616 query->DeviceVcHandle = 0;
617
618 ret = RndisFilterSendRequest(Device, request);
619 if (ret != 0)
620 {
621 goto Cleanup;
622 }
623
624 WaitEventWait(request->WaitEvent);
625
626 // Copy the response back
627 queryComplete = &request->ResponseMessage.Message.QueryComplete;
628
629 if (queryComplete->InformationBufferLength > inresultSize)
630 {
631 ret = -1;
632 goto Cleanup;
633 }
634
635 memcpy(Result,
636 (void*)((ULONG_PTR)queryComplete + queryComplete->InformationBufferOffset),
637 queryComplete->InformationBufferLength);
638
639 *ResultSize = queryComplete->InformationBufferLength;
640
641 Cleanup:
642 if (request)
643 {
644 PutRndisRequest(Device, request);
645 }
646 DPRINT_EXIT(NETVSC);
647
648 return ret;
649 }
650
651 static inline int
652 RndisFilterQueryDeviceMac(
653 RNDIS_DEVICE *Device
654 )
655 {
656 u32 size=HW_MACADDR_LEN;
657
658 return RndisFilterQueryDevice(Device,
659 RNDIS_OID_802_3_PERMANENT_ADDRESS,
660 Device->HwMacAddr,
661 &size);
662 }
663
664 static inline int
665 RndisFilterQueryDeviceLinkStatus(
666 RNDIS_DEVICE *Device
667 )
668 {
669 u32 size=sizeof(u32);
670
671 return RndisFilterQueryDevice(Device,
672 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
673 &Device->LinkStatus,
674 &size);
675 }
676
677 static int
678 RndisFilterSetPacketFilter(
679 RNDIS_DEVICE *Device,
680 u32 NewFilter
681 )
682 {
683 RNDIS_REQUEST *request;
684 RNDIS_SET_REQUEST *set;
685 RNDIS_SET_COMPLETE *setComplete;
686 u32 status;
687 int ret;
688
689 DPRINT_ENTER(NETVSC);
690
691 ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(u32) <= sizeof(RNDIS_MESSAGE));
692
693 request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(u32));
694 if (!request)
695 {
696 ret = -1;
697 goto Cleanup;
698 }
699
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);
705
706 memcpy((void*)(ULONG_PTR)set + sizeof(RNDIS_SET_REQUEST), &NewFilter, sizeof(u32));
707
708 ret = RndisFilterSendRequest(Device, request);
709 if (ret != 0)
710 {
711 goto Cleanup;
712 }
713
714 ret = WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
715 if (!ret)
716 {
717 ret = -1;
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.
720 goto Exit;
721 }
722 else
723 {
724 if (ret > 0)
725 {
726 ret = 0;
727 }
728 setComplete = &request->ResponseMessage.Message.SetComplete;
729 status = setComplete->Status;
730 }
731
732 Cleanup:
733 if (request)
734 {
735 PutRndisRequest(Device, request);
736 }
737 Exit:
738 DPRINT_EXIT(NETVSC);
739
740 return ret;
741 }
742
743 int
744 RndisFilterInit(
745 NETVSC_DRIVER_OBJECT *Driver
746 )
747 {
748 DPRINT_ENTER(NETVSC);
749
750 DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET));
751
752 Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
753 Driver->AdditionalRequestPageBufferCount = 1; // For rndis header
754
755 //Driver->Context = rndisDriver;
756
757 memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
758
759 /*rndisDriver->Driver = Driver;
760
761 ASSERT(Driver->OnLinkStatusChanged);
762 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
763
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;
768
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;
774
775 // Override
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;
784
785 DPRINT_EXIT(NETVSC);
786
787 return 0;
788 }
789
790 static int
791 RndisFilterInitDevice(
792 RNDIS_DEVICE *Device
793 )
794 {
795 RNDIS_REQUEST *request;
796 RNDIS_INITIALIZE_REQUEST *init;
797 RNDIS_INITIALIZE_COMPLETE *initComplete;
798 u32 status;
799 int ret;
800
801 DPRINT_ENTER(NETVSC);
802
803 request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST));
804 if (!request)
805 {
806 ret = -1;
807 goto Cleanup;
808 }
809
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
815
816 Device->State = RNDIS_DEV_INITIALIZING;
817
818 ret = RndisFilterSendRequest(Device, request);
819 if (ret != 0)
820 {
821 Device->State = RNDIS_DEV_UNINITIALIZED;
822 goto Cleanup;
823 }
824
825 WaitEventWait(request->WaitEvent);
826
827 initComplete = &request->ResponseMessage.Message.InitializeComplete;
828 status = initComplete->Status;
829 if (status == RNDIS_STATUS_SUCCESS)
830 {
831 Device->State = RNDIS_DEV_INITIALIZED;
832 ret = 0;
833 }
834 else
835 {
836 Device->State = RNDIS_DEV_UNINITIALIZED;
837 ret = -1;
838 }
839
840 Cleanup:
841 if (request)
842 {
843 PutRndisRequest(Device, request);
844 }
845 DPRINT_EXIT(NETVSC);
846
847 return ret;
848 }
849
850 static void
851 RndisFilterHaltDevice(
852 RNDIS_DEVICE *Device
853 )
854 {
855 RNDIS_REQUEST *request;
856 RNDIS_HALT_REQUEST *halt;
857
858 DPRINT_ENTER(NETVSC);
859
860 // Attempt to do a rndis device halt
861 request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST));
862 if (!request)
863 {
864 goto Cleanup;
865 }
866
867 // Setup the rndis set
868 halt = &request->RequestMessage.Message.HaltRequest;
869 halt->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
870
871 // Ignore return since this msg is optional.
872 RndisFilterSendRequest(Device, request);
873
874 Device->State = RNDIS_DEV_UNINITIALIZED;
875
876 Cleanup:
877 if (request)
878 {
879 PutRndisRequest(Device, request);
880 }
881 DPRINT_EXIT(NETVSC);
882 return;
883 }
884
885
886 static int
887 RndisFilterOpenDevice(
888 RNDIS_DEVICE *Device
889 )
890 {
891 int ret=0;
892
893 DPRINT_ENTER(NETVSC);
894
895 if (Device->State != RNDIS_DEV_INITIALIZED)
896 return 0;
897
898 ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
899 if (ret == 0)
900 {
901 Device->State = RNDIS_DEV_DATAINITIALIZED;
902 }
903
904 DPRINT_EXIT(NETVSC);
905 return ret;
906 }
907
908 static int
909 RndisFilterCloseDevice(
910 RNDIS_DEVICE *Device
911 )
912 {
913 int ret;
914
915 DPRINT_ENTER(NETVSC);
916
917 if (Device->State != RNDIS_DEV_DATAINITIALIZED)
918 return 0;
919
920 ret = RndisFilterSetPacketFilter(Device, 0);
921 if (ret == 0)
922 {
923 Device->State = RNDIS_DEV_INITIALIZED;
924 }
925
926 DPRINT_EXIT(NETVSC);
927
928 return ret;
929 }
930
931
932 int
933 RndisFilterOnDeviceAdd(
934 DEVICE_OBJECT *Device,
935 void *AdditionalInfo
936 )
937 {
938 int ret;
939 NETVSC_DEVICE *netDevice;
940 RNDIS_DEVICE *rndisDevice;
941 NETVSC_DEVICE_INFO *deviceInfo = (NETVSC_DEVICE_INFO*)AdditionalInfo;
942
943 DPRINT_ENTER(NETVSC);
944
945 //rndisDevice = MemAlloc(sizeof(RNDIS_DEVICE));
946 rndisDevice = GetRndisDevice();
947 if (!rndisDevice)
948 {
949 DPRINT_EXIT(NETVSC);
950 return -1;
951 }
952
953 DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
954
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);
959 if (ret != 0)
960 {
961 PutRndisDevice(rndisDevice);
962 DPRINT_EXIT(NETVSC);
963 return ret;
964 }
965
966 //
967 // Initialize the rndis device
968 //
969 netDevice = (NETVSC_DEVICE*)Device->Extension;
970 ASSERT(netDevice);
971 ASSERT(netDevice->Device);
972
973 netDevice->Extension = rndisDevice;
974 rndisDevice->NetDevice = netDevice;
975
976 // Send the rndis initialization message
977 ret = RndisFilterInitDevice(rndisDevice);
978 if (ret != 0)
979 {
980 // TODO: If rndis init failed, we will need to shut down the channel
981 }
982
983 // Get the mac address
984 ret = RndisFilterQueryDeviceMac(rndisDevice);
985 if (ret != 0)
986 {
987 // TODO: shutdown rndis device and the channel
988 }
989
990 DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
991 rndisDevice,
992 rndisDevice->HwMacAddr[0],
993 rndisDevice->HwMacAddr[1],
994 rndisDevice->HwMacAddr[2],
995 rndisDevice->HwMacAddr[3],
996 rndisDevice->HwMacAddr[4],
997 rndisDevice->HwMacAddr[5]);
998
999 memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
1000
1001 RndisFilterQueryDeviceLinkStatus(rndisDevice);
1002
1003 deviceInfo->LinkState = rndisDevice->LinkStatus;
1004 DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, ((deviceInfo->LinkState)?("down"):("up")));
1005
1006 DPRINT_EXIT(NETVSC);
1007
1008 return ret;
1009 }
1010
1011
1012 static int
1013 RndisFilterOnDeviceRemove(
1014 DEVICE_OBJECT *Device
1015 )
1016 {
1017 NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
1018 RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
1019
1020 DPRINT_ENTER(NETVSC);
1021
1022 // Halt and release the rndis device
1023 RndisFilterHaltDevice(rndisDevice);
1024
1025 PutRndisDevice(rndisDevice);
1026 netDevice->Extension = NULL;
1027
1028 // Pass control to inner driver to remove the device
1029 gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
1030
1031 DPRINT_EXIT(NETVSC);
1032
1033 return 0;
1034 }
1035
1036
1037 static void
1038 RndisFilterOnCleanup(
1039 DRIVER_OBJECT *Driver
1040 )
1041 {
1042 DPRINT_ENTER(NETVSC);
1043
1044 DPRINT_EXIT(NETVSC);
1045 }
1046
1047 static int
1048 RndisFilterOnOpen(
1049 DEVICE_OBJECT *Device
1050 )
1051 {
1052 int ret;
1053 NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
1054
1055 DPRINT_ENTER(NETVSC);
1056
1057 ASSERT(netDevice);
1058 ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
1059
1060 DPRINT_EXIT(NETVSC);
1061
1062 return ret;
1063 }
1064
1065 static int
1066 RndisFilterOnClose(
1067 DEVICE_OBJECT *Device
1068 )
1069 {
1070 int ret;
1071 NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
1072
1073 DPRINT_ENTER(NETVSC);
1074
1075 ASSERT(netDevice);
1076 ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
1077
1078 DPRINT_EXIT(NETVSC);
1079
1080 return ret;
1081 }
1082
1083
1084 static int
1085 RndisFilterOnSend(
1086 DEVICE_OBJECT *Device,
1087 NETVSC_PACKET *Packet
1088 )
1089 {
1090 int ret=0;
1091 RNDIS_FILTER_PACKET *filterPacket;
1092 RNDIS_MESSAGE *rndisMessage;
1093 RNDIS_PACKET *rndisPacket;
1094 u32 rndisMessageSize;
1095
1096 DPRINT_ENTER(NETVSC);
1097
1098 // Add the rndis header
1099 filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
1100 ASSERT(filterPacket);
1101
1102 memset(filterPacket, 0, sizeof(RNDIS_FILTER_PACKET));
1103
1104 rndisMessage = &filterPacket->Message;
1105 rndisMessageSize = RNDIS_MESSAGE_SIZE(RNDIS_PACKET);
1106
1107 rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
1108 rndisMessage->MessageLength = Packet->TotalDataBufferLength + rndisMessageSize;
1109
1110 rndisPacket = &rndisMessage->Message.Packet;
1111 rndisPacket->DataOffset = sizeof(RNDIS_PACKET);
1112 rndisPacket->DataLength = Packet->TotalDataBufferLength;
1113
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;
1118
1119 // Save the packet send completion and context
1120 filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
1121 filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
1122
1123 // Use ours
1124 Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
1125 Packet->Completion.Send.SendCompletionContext = filterPacket;
1126
1127 ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
1128 if (ret != 0)
1129 {
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;
1133 }
1134
1135 DPRINT_EXIT(NETVSC);
1136
1137 return ret;
1138 }
1139
1140 static void
1141 RndisFilterOnSendCompletion(
1142 void *Context)
1143 {
1144 RNDIS_FILTER_PACKET *filterPacket = (RNDIS_FILTER_PACKET *)Context;
1145
1146 DPRINT_ENTER(NETVSC);
1147
1148 // Pass it back to the original handler
1149 filterPacket->OnCompletion(filterPacket->CompletionContext);
1150
1151 DPRINT_EXIT(NETVSC);
1152 }
1153
1154
1155 static void
1156 RndisFilterOnSendRequestCompletion(
1157 void *Context
1158 )
1159 {
1160 DPRINT_ENTER(NETVSC);
1161
1162 // Noop
1163 DPRINT_EXIT(NETVSC);
1164 }
This page took 0.05369 seconds and 6 git commands to generate.