| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147 |
- /*
- * TAP-Windows -- A kernel driver to provide virtual tap
- * device functionality on Windows.
- *
- * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
- *
- * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
- * and is released under the GPL version 2 (see below).
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program (see the file COPYING included with this
- * distribution); if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- //======================================================
- // This driver is designed to work on Win 2000 or higher
- // versions of Windows.
- //
- // It is SMP-safe and handles NDIS 5 power management.
- //
- // By default we operate as a "tap" virtual ethernet
- // 802.3 interface, but we can emulate a "tun"
- // interface (point-to-point IPv4) through the
- // TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT or
- // TAP_WIN_IOCTL_CONFIG_TUN ioctl.
- //======================================================
- #include "tap-windows.h"
- #include "config.h"
- #define NDIS_MINIPORT_DRIVER
- #define BINARY_COMPATIBLE 0
- #define NDIS50_MINIPORT 1
- #define NDIS_WDM 0
- #define NDIS50 1
- #define NTSTRSAFE_LIB
- // Debug info output
- #define ALSO_DBGPRINT 1
- #define DEBUGP_AT_DISPATCH 0
- //========================================================
- // Check for truncated IPv4 packets, log errors if found.
- //========================================================
- #define PACKET_TRUNCATION_CHECK 0
- //========================================================
- // EXPERIMENTAL -- Configure TAP device object to be
- // accessible from non-administrative accounts, based
- // on an advanced properties setting.
- //
- // Duplicates the functionality of OpenVPN's
- // --allow-nonadmin directive.
- //========================================================
- #define ENABLE_NONADMIN 1
- #if defined(DDKVER_MAJOR) && DDKVER_MAJOR < 5600
- #include <ndis.h>
- #include <ntstrsafe.h>
- #include <ntddk.h>
- #else
- #include <ntifs.h>
- #include <ndis.h>
- #include <ntstrsafe.h>
- #endif
- #include "lock.h"
- #include "constants.h"
- #include "proto.h"
- #include "error.h"
- #include "endian.h"
- #include "dhcp.h"
- #include "types.h"
- #include "prototypes.h"
- #include "mem.c"
- #include "macinfo.c"
- #include "error.c"
- #include "dhcp.c"
- #include "instance.c"
- #define IS_UP(ta) \
- ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning)
- #define INCREMENT_STAT(s) ++(s)
- #define NAME_BUFFER_SIZE 80
- //========================================================
- // Globals
- //========================================================
- NDIS_HANDLE g_NdisWrapperHandle;
- const UINT g_SupportedOIDList[] = {
- OID_GEN_HARDWARE_STATUS,
- OID_GEN_MEDIA_SUPPORTED,
- OID_GEN_MEDIA_IN_USE,
- OID_GEN_MAXIMUM_LOOKAHEAD,
- OID_GEN_MAC_OPTIONS,
- OID_GEN_LINK_SPEED,
- OID_GEN_TRANSMIT_BLOCK_SIZE,
- OID_GEN_RECEIVE_BLOCK_SIZE,
- OID_GEN_VENDOR_DESCRIPTION,
- OID_GEN_DRIVER_VERSION,
- OID_GEN_XMIT_OK,
- OID_GEN_RCV_OK,
- OID_GEN_XMIT_ERROR,
- OID_GEN_RCV_ERROR,
- OID_802_3_PERMANENT_ADDRESS,
- OID_802_3_CURRENT_ADDRESS,
- OID_GEN_RCV_NO_BUFFER,
- OID_802_3_RCV_ERROR_ALIGNMENT,
- OID_802_3_XMIT_ONE_COLLISION,
- OID_802_3_XMIT_MORE_COLLISIONS,
- OID_802_3_MULTICAST_LIST,
- OID_802_3_MAXIMUM_LIST_SIZE,
- OID_GEN_VENDOR_ID,
- OID_GEN_CURRENT_LOOKAHEAD,
- OID_GEN_CURRENT_PACKET_FILTER,
- OID_GEN_PROTOCOL_OPTIONS,
- OID_GEN_MAXIMUM_TOTAL_SIZE,
- OID_GEN_TRANSMIT_BUFFER_SPACE,
- OID_GEN_RECEIVE_BUFFER_SPACE,
- OID_GEN_MAXIMUM_FRAME_SIZE,
- OID_GEN_VENDOR_DRIVER_VERSION,
- OID_GEN_MAXIMUM_SEND_PACKETS,
- OID_GEN_MEDIA_CONNECT_STATUS,
- OID_GEN_SUPPORTED_LIST
- };
- //============================================================
- // Driver Entry
- //============================================================
- #pragma NDIS_INIT_FUNCTION (DriverEntry)
- DRIVER_INITIALIZE DriverEntry;
- NTSTATUS
- DriverEntry (IN PDRIVER_OBJECT p_DriverObject,
- IN PUNICODE_STRING p_RegistryPath)
- {
- NDIS_STATUS l_Status = NDIS_STATUS_FAILURE;
- NDIS_MINIPORT_CHARACTERISTICS *l_Properties = NULL;
- //========================================================
- // Notify NDIS that a new miniport driver is initializing.
- //========================================================
- NdisMInitializeWrapper (&g_NdisWrapperHandle,
- p_DriverObject,
- p_RegistryPath, NULL);
- //======================
- // Global initialization
- //======================
- #if DBG
- MyDebugInit (10000); // Allocate debugging text space
- #endif
- if (!InitInstanceList ())
- {
- DEBUGP (("[TAP] Allocation failed for adapter instance list\n"));
- goto cleanup;
- }
- //=======================================
- // Set and register miniport entry points
- //=======================================
- l_Properties = MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS), TRUE);
- if (l_Properties == NULL)
- {
- DEBUGP (("[TAP] Allocation failed for miniport entry points\n"));
- goto cleanup;
- }
- l_Properties->MajorNdisVersion = TAP_NDIS_MAJOR_VERSION;
- l_Properties->MinorNdisVersion = TAP_NDIS_MINOR_VERSION;
- l_Properties->InitializeHandler = AdapterCreate;
- l_Properties->HaltHandler = AdapterHalt;
- l_Properties->ResetHandler = AdapterReset; /* DISPATCH_LEVEL */
- l_Properties->TransferDataHandler = AdapterReceive; /* DISPATCH_LEVEL */
- l_Properties->SendHandler = AdapterTransmit; /* DISPATCH_LEVEL */
- l_Properties->QueryInformationHandler = AdapterQuery; /* DISPATCH_LEVEL */
- l_Properties->SetInformationHandler = AdapterModify; /* DISPATCH_LEVEL */
- switch (l_Status =
- NdisMRegisterMiniport (g_NdisWrapperHandle, l_Properties,
- sizeof (NDIS_MINIPORT_CHARACTERISTICS)))
- {
- case NDIS_STATUS_SUCCESS:
- {
- DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION,
- __DATE__,
- __TIME__));
- DEBUGP (("Registry Path: '%.*S'\n", p_RegistryPath->Length/2, p_RegistryPath->Buffer));
- break;
- }
- case NDIS_STATUS_BAD_CHARACTERISTICS:
- {
- DEBUGP (("[TAP] Miniport characteristics were badly defined\n"));
- NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
- break;
- }
- case NDIS_STATUS_BAD_VERSION:
- {
- DEBUGP
- (("[TAP] NDIS Version is wrong for the given characteristics\n"));
- NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
- break;
- }
- case NDIS_STATUS_RESOURCES:
- {
- DEBUGP (("[TAP] Insufficient resources\n"));
- NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
- break;
- }
- default:
- case NDIS_STATUS_FAILURE:
- {
- DEBUGP (("[TAP] Unknown fatal registration error\n"));
- NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
- break;
- }
- }
- cleanup:
- if (l_Properties)
- MemFree (l_Properties, sizeof (NDIS_MINIPORT_CHARACTERISTICS));
- if (l_Status == NDIS_STATUS_SUCCESS)
- NdisMRegisterUnloadHandler (g_NdisWrapperHandle, TapDriverUnload);
- else
- TapDriverUnload (p_DriverObject);
- return l_Status;
- }
- //============================================================
- // Driver Unload
- //============================================================
- DRIVER_UNLOAD TapDriverUnload;
- VOID
- TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject)
- {
- DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION,
- __DATE__,
- __TIME__,
- NInstances(),
- InstanceMaxBucketSize()));
- FreeInstanceList ();
- //==============================
- // Free debugging text space
- //==============================
- #if DBG
- MyDebugFree ();
- #endif
- }
- //==========================================================
- // Adapter Initialization
- //==========================================================
- NDIS_STATUS AdapterCreate
- (OUT PNDIS_STATUS p_ErrorStatus,
- OUT PUINT p_MediaIndex,
- IN PNDIS_MEDIUM p_Media,
- IN UINT p_MediaCount,
- IN NDIS_HANDLE p_AdapterHandle,
- IN NDIS_HANDLE p_ConfigurationHandle)
- {
- TapAdapterPointer l_Adapter = NULL;
- NDIS_MEDIUM l_PreferredMedium = NdisMedium802_3; // Ethernet
- BOOLEAN l_MacFromRegistry = FALSE;
- UINT l_Index;
- NDIS_STATUS status;
- #if ENABLE_NONADMIN
- BOOLEAN enable_non_admin = FALSE;
- #endif
- DEBUGP (("[TAP] AdapterCreate called\n"));
- //====================================
- // Make sure adapter type is supported
- //====================================
- for (l_Index = 0;
- l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium;
- ++l_Index);
- if (l_Index == p_MediaCount)
- {
- DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n",
- l_PreferredMedium));
- return NDIS_STATUS_UNSUPPORTED_MEDIA;
- }
- *p_MediaIndex = l_Index;
- //=========================================
- // Allocate memory for TapAdapter structure
- //=========================================
- l_Adapter = MemAlloc (sizeof (TapAdapter), TRUE);
- if (l_Adapter == NULL)
- {
- DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
- return NDIS_STATUS_RESOURCES;
- }
- //==========================================
- // Inform the NDIS library about significant
- // features of our virtual NIC.
- //==========================================
- NdisMSetAttributesEx
- (p_AdapterHandle,
- (NDIS_HANDLE) l_Adapter,
- 16,
- NDIS_ATTRIBUTE_DESERIALIZE
- | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
- | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT
- | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
- NdisInterfaceInternal);
- //=====================================
- // Initialize simple Adapter parameters
- //=====================================
- l_Adapter->m_Lookahead = DEFAULT_PACKET_LOOKAHEAD;
- l_Adapter->m_Medium = l_PreferredMedium;
- l_Adapter->m_DeviceState = '?';
- l_Adapter->m_MiniportAdapterHandle = p_AdapterHandle;
- //==================================
- // Allocate spinlock for controlling
- // access to multicast address list.
- //==================================
- NdisAllocateSpinLock (&l_Adapter->m_MCLock);
- l_Adapter->m_MCLockAllocated = TRUE;
- //====================================================
- // Register a shutdown handler which will be called
- // on system restart/shutdown to halt our virtual NIC.
- //====================================================
- NdisMRegisterAdapterShutdownHandler (p_AdapterHandle, l_Adapter,
- AdapterHalt);
- l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE;
- //============================================
- // Get parameters from registry which were set
- // in the adapter advanced properties dialog.
- //============================================
- {
- NDIS_STATUS status;
- NDIS_HANDLE configHandle;
- NDIS_CONFIGURATION_PARAMETER *parm;
- // set defaults in case our registry query fails
- l_Adapter->m_MTU = ETHERNET_MTU;
- l_Adapter->m_MediaStateAlwaysConnected = FALSE;
- l_Adapter->m_MediaState = FALSE;
- NdisOpenConfiguration (&status, &configHandle, p_ConfigurationHandle);
- if (status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] Couldn't open adapter registry\n"));
- AdapterFreeResources (l_Adapter);
- return status;
- }
- //====================================
- // Allocate and construct adapter name
- //====================================
- {
-
- NDIS_STRING mkey = NDIS_STRING_CONST("MiniportName");
- NDIS_STRING vkey = NDIS_STRING_CONST("NdisVersion");
- NDIS_STATUS vstatus;
- NDIS_CONFIGURATION_PARAMETER *vparm;
- NdisReadConfiguration (&vstatus, &vparm, configHandle, &vkey, NdisParameterInteger);
- if (vstatus == NDIS_STATUS_SUCCESS)
- DEBUGP (("[TAP] NdisReadConfiguration NdisVersion=%X\n", vparm->ParameterData.IntegerData));
- NdisReadConfiguration (&status, &parm, configHandle, &mkey, NdisParameterString);
- if (status == NDIS_STATUS_SUCCESS)
- {
- if (parm->ParameterType == NdisParameterString)
- {
- DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%.*S)\n",
- parm->ParameterData.StringData.Length/2,
- parm->ParameterData.StringData.Buffer));
- if (RtlUnicodeStringToAnsiString (
- &l_Adapter->m_NameAnsi,
- &parm->ParameterData.StringData,
- TRUE) != STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] MiniportName failed\n"));
- status = NDIS_STATUS_RESOURCES;
- }
- }
- }
- else
- {
- /* "MiniportName" is available only XP and above. Not on Windows 2000. */
- if (vstatus == NDIS_STATUS_SUCCESS && vparm->ParameterData.IntegerData == 0x50000)
- {
- /* Fallback for Windows 2000 with NDIS version 5.00.00
- Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */
- if (RtlUnicodeStringToAnsiString (&l_Adapter->m_NameAnsi,
- &((struct WIN2K_NDIS_MINIPORT_BLOCK *) p_AdapterHandle)->MiniportName,
- TRUE) != STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] MiniportName (W2K) failed\n"));
- status = NDIS_STATUS_RESOURCES;
- }
- else
- {
- DEBUGP (("[TAP] MiniportName (W2K) succeeded: %s\n", l_Adapter->m_NameAnsi.Buffer));
- status = NDIS_STATUS_SUCCESS;
- }
- }
- }
- }
- /* Can't continue without name (see macro 'NAME') */
- if (status != NDIS_STATUS_SUCCESS || !l_Adapter->m_NameAnsi.Buffer)
- {
- NdisCloseConfiguration (configHandle);
- AdapterFreeResources (l_Adapter);
- DEBUGP (("[TAP] failed to get miniport name\n"));
- return NDIS_STATUS_RESOURCES;
- }
- /* Read MTU setting from registry */
- {
- NDIS_STRING key = NDIS_STRING_CONST("MTU");
- NdisReadConfiguration (&status, &parm, configHandle,
- &key, NdisParameterInteger);
- if (status == NDIS_STATUS_SUCCESS)
- {
- if (parm->ParameterType == NdisParameterInteger)
- {
- int mtu = parm->ParameterData.IntegerData;
- if (mtu < MINIMUM_MTU)
- mtu = MINIMUM_MTU;
- if (mtu > MAXIMUM_MTU)
- mtu = MAXIMUM_MTU;
- l_Adapter->m_MTU = mtu;
- }
- }
- }
- /* Read Media Status setting from registry */
- {
- NDIS_STRING key = NDIS_STRING_CONST("MediaStatus");
- NdisReadConfiguration (&status, &parm, configHandle,
- &key, NdisParameterInteger);
- if (status == NDIS_STATUS_SUCCESS)
- {
- if (parm->ParameterType == NdisParameterInteger)
- {
- if (parm->ParameterData.IntegerData)
- {
- l_Adapter->m_MediaStateAlwaysConnected = TRUE;
- l_Adapter->m_MediaState = TRUE;
- }
- }
- }
- }
- #if ENABLE_NONADMIN
- /* Read AllowNonAdmin setting from registry */
- {
- NDIS_STRING key = NDIS_STRING_CONST("AllowNonAdmin");
- NdisReadConfiguration (&status, &parm, configHandle,
- &key, NdisParameterInteger);
- if (status == NDIS_STATUS_SUCCESS)
- {
- if (parm->ParameterType == NdisParameterInteger)
- {
- if (parm->ParameterData.IntegerData)
- {
- enable_non_admin = TRUE;
- }
- }
- }
- }
- #endif
- /* Read optional MAC setting from registry */
- {
- NDIS_STRING key = NDIS_STRING_CONST("MAC");
- ANSI_STRING mac_string;
- NdisReadConfiguration (&status, &parm, configHandle,
- &key, NdisParameterString);
- if (status == NDIS_STATUS_SUCCESS)
- {
- if (parm->ParameterType == NdisParameterString)
- {
- if (RtlUnicodeStringToAnsiString (&mac_string, &parm->ParameterData.StringData, TRUE) == STATUS_SUCCESS)
- {
- l_MacFromRegistry = ParseMAC (l_Adapter->m_MAC, mac_string.Buffer);
- RtlFreeAnsiString (&mac_string);
- }
- }
- }
- }
- NdisCloseConfiguration (configHandle);
- DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter), l_Adapter->m_MTU));
- }
- //==================================
- // Store and update MAC address info
- //==================================
- if (!l_MacFromRegistry)
- GenerateRandomMac (l_Adapter->m_MAC, NAME (l_Adapter));
- DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n",
- NAME (l_Adapter),
- l_Adapter->m_MAC[0], l_Adapter->m_MAC[1], l_Adapter->m_MAC[2],
- l_Adapter->m_MAC[3], l_Adapter->m_MAC[4], l_Adapter->m_MAC[5]));
- //==================
- // Set broadcast MAC
- //==================
- {
- int i;
- for (i = 0; i < sizeof (MACADDR); ++i)
- l_Adapter->m_MAC_Broadcast[i] = 0xFF;
- }
- //====================================
- // Initialize TAP device
- //====================================
- {
- NDIS_STATUS tap_status;
- tap_status = CreateTapDevice (&l_Adapter->m_Extension, NAME (l_Adapter));
- if (tap_status != NDIS_STATUS_SUCCESS)
- {
- AdapterFreeResources (l_Adapter);
- DEBUGP (("[TAP] CreateTapDevice failed\n"));
- return tap_status;
- }
- }
- if (!AddAdapterToInstanceList (l_Adapter))
- {
- NOTE_ERROR ();
- TapDeviceFreeResources (&l_Adapter->m_Extension);
- AdapterFreeResources (l_Adapter);
- DEBUGP (("[TAP] AddAdapterToInstanceList failed\n"));
- return NDIS_STATUS_RESOURCES;
- }
- l_Adapter->m_InterfaceIsRunning = TRUE;
- #if ENABLE_NONADMIN
- if (enable_non_admin)
- AllowNonAdmin (&l_Adapter->m_Extension);
- #endif
- return NDIS_STATUS_SUCCESS;
- }
- VOID
- AdapterHalt (IN NDIS_HANDLE p_AdapterContext)
- {
- BOOLEAN status;
- TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
- NOTE_ERROR ();
- l_Adapter->m_InterfaceIsRunning = FALSE;
- DEBUGP (("[%s] is being halted\n", NAME (l_Adapter)));
-
- DestroyTapDevice (&l_Adapter->m_Extension);
- // Free resources
- DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter)));
- AdapterFreeResources (l_Adapter);
- status = RemoveAdapterFromInstanceList (l_Adapter);
- DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status));
- DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION,
- __DATE__,
- __TIME__));
- }
- VOID
- AdapterFreeResources (TapAdapterPointer p_Adapter)
- {
- MYASSERT (!p_Adapter->m_CalledAdapterFreeResources);
- p_Adapter->m_CalledAdapterFreeResources = TRUE;
- if (p_Adapter->m_NameAnsi.Buffer)
- RtlFreeAnsiString (&p_Adapter->m_NameAnsi);
-
- if (p_Adapter->m_RegisteredAdapterShutdownHandler)
- NdisMDeregisterAdapterShutdownHandler (p_Adapter->m_MiniportAdapterHandle);
- if (p_Adapter->m_MCLockAllocated)
- NdisFreeSpinLock (&p_Adapter->m_MCLock);
- }
- VOID
- DestroyTapDevice (TapExtensionPointer p_Extension)
- {
- DEBUGP (("[%s] Destroying tap device\n", p_Extension->m_TapName));
- //======================================
- // Let clients know we are shutting down
- //======================================
- p_Extension->m_TapIsRunning = FALSE;
- p_Extension->m_TapOpens = 0;
- p_Extension->m_Halt = TRUE;
- //=====================================
- // If we are concurrently executing in
- // TapDeviceHook or AdapterTransmit,
- // give those calls time to finish.
- // Note that we must be running at IRQL
- // < DISPATCH_LEVEL in order to call
- // NdisMSleep.
- //=====================================
- NdisMSleep (500000);
- //===========================================================
- // Exhaust IRP and packet queues. Any pending IRPs will
- // be cancelled, causing user-space to get this error
- // on overlapped reads:
- // The I/O operation has been aborted because of either a
- // thread exit or an application request. (code=995)
- // It's important that user-space close the device handle
- // when this code is returned, so that when we finally
- // do a NdisMDeregisterDevice, the device reference count
- // is 0. Otherwise the driver will not unload even if the
- // the last adapter has been halted.
- //===========================================================
- FlushQueues (p_Extension);
- NdisMSleep (500000); // give user space time to respond to IRP cancel
- TapDeviceFreeResources (p_Extension);
- }
- VOID
- TapDeviceFreeResources (TapExtensionPointer p_Extension)
- {
- MYASSERT (p_Extension);
- MYASSERT (!p_Extension->m_CalledTapDeviceFreeResources);
- p_Extension->m_CalledTapDeviceFreeResources = TRUE;
- if (p_Extension->m_PacketQueue)
- QueueFree (p_Extension->m_PacketQueue);
- if (p_Extension->m_IrpQueue)
- QueueFree (p_Extension->m_IrpQueue);
- if (p_Extension->m_InjectQueue)
- QueueFree (p_Extension->m_InjectQueue);
- if (p_Extension->m_CreatedUnicodeLinkName)
- RtlFreeUnicodeString (&p_Extension->m_UnicodeLinkName);
- //==========================================================
- // According to DDK docs, the device is not actually deleted
- // until its reference count falls to zero. That means we
- // still need to gracefully fail TapDeviceHook requests
- // after this point, otherwise ugly things would happen if
- // the device was disabled (e.g. in the network connections
- // control panel) while a userspace app still held an open
- // file handle to it.
- //==========================================================
-
- if (p_Extension->m_TapDevice)
- {
- BOOLEAN status;
- status = (NdisMDeregisterDevice (p_Extension->m_TapDeviceHandle)
- == NDIS_STATUS_SUCCESS);
- DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status));
- }
- if (p_Extension->m_TapName)
- MemFree (p_Extension->m_TapName, NAME_BUFFER_SIZE);
-
- if (p_Extension->m_InjectDpcInitialized)
- KeRemoveQueueDpc (&p_Extension->m_InjectDpc);
- if (p_Extension->m_AllocatedSpinlocks)
- {
- NdisFreeSpinLock (&p_Extension->m_QueueLock);
- NdisFreeSpinLock (&p_Extension->m_InjectLock);
- }
- }
- //========================================================================
- // Tap Device Initialization
- //========================================================================
- NDIS_STATUS
- CreateTapDevice (TapExtensionPointer p_Extension, const char *p_Name)
- {
- # define SIZEOF_DISPATCH (sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1))
- PDRIVER_DISPATCH *l_Dispatch = NULL;
- ANSI_STRING l_TapString, l_LinkString;
- UNICODE_STRING l_TapUnicode;
- BOOLEAN l_FreeTapUnicode = FALSE;
- NTSTATUS l_Status, l_Return = NDIS_STATUS_SUCCESS;
- const char *l_UsableName;
- DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION,
- p_Name));
- NdisZeroMemory (p_Extension, sizeof (TapExtension));
- INIT_MUTEX (&p_Extension->m_OpenCloseMutex);
- l_LinkString.Buffer = NULL;
- l_TapString.Buffer = NULL;
- l_TapString.MaximumLength = l_LinkString.MaximumLength = NAME_BUFFER_SIZE;
- //=======================================
- // Set TAP device entry points
- //=======================================
- if ((l_Dispatch = MemAlloc (SIZEOF_DISPATCH, TRUE)) == NULL)
- {
- DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- l_Dispatch[IRP_MJ_DEVICE_CONTROL] = TapDeviceHook;
- l_Dispatch[IRP_MJ_READ] = TapDeviceHook;
- l_Dispatch[IRP_MJ_WRITE] = TapDeviceHook;
- l_Dispatch[IRP_MJ_CREATE] = TapDeviceHook;
- l_Dispatch[IRP_MJ_CLOSE] = TapDeviceHook;
- //==================================
- // Find the beginning of the GUID
- //==================================
- l_UsableName = p_Name;
- while (*l_UsableName != '{')
- {
- if (*l_UsableName == '\0')
- {
- DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- ++l_UsableName;
- }
- //==================================
- // Allocate pool for TAP device name
- //==================================
- if ((p_Extension->m_TapName = l_TapString.Buffer =
- MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL)
- {
- DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- //================================================
- // Allocate pool for TAP symbolic link name buffer
- //================================================
- if ((l_LinkString.Buffer =
- MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL)
- {
- DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n",
- p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- //=======================================================
- // Set TAP device name
- //=======================================================
- l_Status = RtlStringCchPrintfExA
- (l_TapString.Buffer,
- l_TapString.MaximumLength,
- NULL,
- NULL,
- STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
- "%s%s%s",
- SYSDEVICEDIR,
- l_UsableName,
- TAP_WIN_SUFFIX);
- if (l_Status != STATUS_SUCCESS)
- {
- DEBUGP (("[%s] couldn't format TAP device name\n",
- p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- l_TapString.Length = (USHORT) strlen (l_TapString.Buffer);
- DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer));
- //=======================================================
- // Set TAP link name
- //=======================================================
- l_Status = RtlStringCchPrintfExA
- (l_LinkString.Buffer,
- l_LinkString.MaximumLength,
- NULL,
- NULL,
- STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
- "%s%s%s",
- USERDEVICEDIR,
- l_UsableName,
- TAP_WIN_SUFFIX);
- if (l_Status != STATUS_SUCCESS)
- {
- DEBUGP (("[%s] couldn't format TAP device symbolic link\n",
- p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- l_LinkString.Length = (USHORT) strlen (l_LinkString.Buffer);
- DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString.Buffer));
- //==================================================
- // Convert strings to unicode
- //==================================================
- if (RtlAnsiStringToUnicodeString (&l_TapUnicode, &l_TapString, TRUE) !=
- STATUS_SUCCESS)
- {
- DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n",
- p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- l_FreeTapUnicode = TRUE;
- if (RtlAnsiStringToUnicodeString
- (&p_Extension->m_UnicodeLinkName, &l_LinkString, TRUE)
- != STATUS_SUCCESS)
- {
- DEBUGP
- (("[%s] Couldn't allocate unicode string for symbolic link name\n",
- p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- p_Extension->m_CreatedUnicodeLinkName = TRUE;
- //==================================================
- // Create new TAP device with symbolic
- // link and associate with adapter.
- //==================================================
- l_Status = NdisMRegisterDevice
- (g_NdisWrapperHandle,
- &l_TapUnicode,
- &p_Extension->m_UnicodeLinkName,
- l_Dispatch,
- &p_Extension->m_TapDevice,
- &p_Extension->m_TapDeviceHandle
- );
- if (l_Status != STATUS_SUCCESS)
- {
- DEBUGP (("[%s] couldn't be created\n", p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- /* Set TAP device flags */
- p_Extension->m_TapDevice->Flags |= DO_DIRECT_IO;
- //========================================================
- // Initialize Packet and IRP queues.
- //
- // The packet queue is used to buffer data which has been
- // "transmitted" by the virtual NIC, before user space
- // has had a chance to read it.
- //
- // The IRP queue is used to buffer pending I/O requests
- // from userspace, i.e. read requests on the TAP device
- // waiting for the system to "transmit" something through
- // the virtual NIC.
- //
- // Basically, packets in the packet queue are used
- // to satisfy IRP requests in the IRP queue.
- //
- // QueueLock is used to lock the packet queue used
- // for the TAP-Windows NIC -> User Space packet flow direction.
- //
- // All accesses to packet or IRP queues should be
- // bracketed by the QueueLock spinlock,
- // in order to be SMP-safe.
- //========================================================
- NdisAllocateSpinLock (&p_Extension->m_QueueLock);
- NdisAllocateSpinLock (&p_Extension->m_InjectLock);
- p_Extension->m_AllocatedSpinlocks = TRUE;
- p_Extension->m_PacketQueue = QueueInit (PACKET_QUEUE_SIZE);
- p_Extension->m_IrpQueue = QueueInit (IRP_QUEUE_SIZE);
- p_Extension->m_InjectQueue = QueueInit (INJECT_QUEUE_SIZE);
- if (!p_Extension->m_PacketQueue
- || !p_Extension->m_IrpQueue
- || !p_Extension->m_InjectQueue)
- {
- DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name));
- l_Return = NDIS_STATUS_RESOURCES;
- goto cleanup;
- }
- //=================================================================
- // Initialize deferred procedure call for DHCP/ARP packet injection
- //=================================================================
- KeInitializeDpc (&p_Extension->m_InjectDpc, InjectPacketDpc, NULL);
- p_Extension->m_InjectDpcInitialized = TRUE;
- //========================
- // Finalize initialization
- //========================
- p_Extension->m_TapIsRunning = TRUE;
- DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name,
- p_Extension->m_TapName));
- cleanup:
- if (l_FreeTapUnicode)
- RtlFreeUnicodeString (&l_TapUnicode);
- if (l_LinkString.Buffer)
- MemFree (l_LinkString.Buffer, NAME_BUFFER_SIZE);
- if (l_Dispatch)
- MemFree (l_Dispatch, SIZEOF_DISPATCH);
- if (l_Return != NDIS_STATUS_SUCCESS)
- TapDeviceFreeResources (p_Extension);
- return l_Return;
- }
- #undef SIZEOF_DISPATCH
- //========================================================
- // Adapter Control
- //========================================================
- NDIS_STATUS
- AdapterReset (OUT PBOOLEAN p_AddressingReset, IN NDIS_HANDLE p_AdapterContext)
- {
- TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
- DEBUGP (("[%s] is resetting\n", NAME (l_Adapter)));
- return NDIS_STATUS_SUCCESS;
- }
- NDIS_STATUS AdapterReceive
- (OUT PNDIS_PACKET p_Packet,
- OUT PUINT p_Transferred,
- IN NDIS_HANDLE p_AdapterContext,
- IN NDIS_HANDLE p_ReceiveContext,
- IN UINT p_Offset,
- IN UINT p_ToTransfer)
- {
- return NDIS_STATUS_SUCCESS;
- }
- //==============================================================
- // Adapter Option Query/Modification
- //==============================================================
- NDIS_STATUS AdapterQuery
- (IN NDIS_HANDLE p_AdapterContext,
- IN NDIS_OID p_OID,
- IN PVOID p_Buffer,
- IN ULONG p_BufferLength,
- OUT PULONG p_BytesWritten, OUT PULONG p_BytesNeeded)
- {
- TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
- TapAdapterQuery l_Query, *l_QueryPtr = &l_Query;
- NDIS_STATUS l_Status = NDIS_STATUS_SUCCESS;
- UINT l_QueryLength = 4;
- BOOLEAN lock_succeeded;
- NdisZeroMemory (&l_Query, sizeof (l_Query));
- switch (p_OID)
- {
- //===================================================================
- // Vendor & Driver version Info
- //===================================================================
- case OID_GEN_VENDOR_DESCRIPTION:
- l_QueryPtr = (TapAdapterQueryPointer) PRODUCT_TAP_WIN_DEVICE_DESCRIPTION;
- l_QueryLength = strlen (PRODUCT_TAP_WIN_DEVICE_DESCRIPTION) + 1;
- break;
- case OID_GEN_VENDOR_ID:
- l_Query.m_Long = 0xffffff;
- break;
- case OID_GEN_DRIVER_VERSION:
- l_Query.m_Short =
- (((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT)
- TAP_NDIS_MINOR_VERSION);
- l_QueryLength = sizeof (unsigned short);
- break;
- case OID_GEN_VENDOR_DRIVER_VERSION:
- l_Query.m_Long =
- (((USHORT) PRODUCT_TAP_WIN_MAJOR) << 8 | (USHORT)
- PRODUCT_TAP_WIN_MINOR);
- break;
- //=================================================================
- // Statistics
- //=================================================================
- case OID_GEN_RCV_NO_BUFFER:
- l_Query.m_Long = 0;
- break;
- case OID_802_3_RCV_ERROR_ALIGNMENT:
- l_Query.m_Long = 0;
- break;
- case OID_802_3_XMIT_ONE_COLLISION:
- l_Query.m_Long = 0;
- break;
- case OID_802_3_XMIT_MORE_COLLISIONS:
- l_Query.m_Long = 0;
- break;
- case OID_GEN_XMIT_OK:
- l_Query.m_Long = l_Adapter->m_Tx;
- break;
- case OID_GEN_RCV_OK:
- l_Query.m_Long = l_Adapter->m_Rx;
- break;
- case OID_GEN_XMIT_ERROR:
- l_Query.m_Long = l_Adapter->m_TxErr;
- break;
- case OID_GEN_RCV_ERROR:
- l_Query.m_Long = l_Adapter->m_RxErr;
- break;
- //===================================================================
- // Device & Protocol Options
- //===================================================================
- case OID_GEN_SUPPORTED_LIST:
- l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList;
- l_QueryLength = sizeof (g_SupportedOIDList);
- break;
- case OID_GEN_MAC_OPTIONS:
- // This MUST be here !!!
- l_Query.m_Long = (NDIS_MAC_OPTION_RECEIVE_SERIALIZED
- | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
- | NDIS_MAC_OPTION_NO_LOOPBACK
- | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND);
- break;
- case OID_GEN_CURRENT_PACKET_FILTER:
- l_Query.m_Long =
- (NDIS_PACKET_TYPE_ALL_LOCAL |
- NDIS_PACKET_TYPE_BROADCAST |
- NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL);
- break;
- case OID_GEN_PROTOCOL_OPTIONS:
- l_Query.m_Long = 0;
- break;
- //==================================================================
- // Device Info
- //==================================================================
- case OID_GEN_MEDIA_CONNECT_STATUS:
- l_Query.m_Long = l_Adapter->m_MediaState
- ? NdisMediaStateConnected : NdisMediaStateDisconnected;
- break;
- case OID_GEN_HARDWARE_STATUS:
- l_Query.m_HardwareStatus = NdisHardwareStatusReady;
- l_QueryLength = sizeof (NDIS_HARDWARE_STATUS);
- break;
- case OID_GEN_MEDIA_SUPPORTED:
- case OID_GEN_MEDIA_IN_USE:
- l_Query.m_Medium = l_Adapter->m_Medium;
- l_QueryLength = sizeof (NDIS_MEDIUM);
- break;
- case OID_GEN_PHYSICAL_MEDIUM:
- l_Query.m_PhysicalMedium = NdisPhysicalMediumUnspecified;
- l_QueryLength = sizeof (NDIS_PHYSICAL_MEDIUM);
- break;
-
- case OID_GEN_LINK_SPEED:
- l_Query.m_Long = 100000; // rate / 100 bps
- break;
- case OID_802_3_PERMANENT_ADDRESS:
- case OID_802_3_CURRENT_ADDRESS:
- COPY_MAC (l_Query.m_MacAddress, l_Adapter->m_MAC);
- l_QueryLength = sizeof (MACADDR);
- break;
- //==================================================================
- // Limits
- //==================================================================
- case OID_GEN_MAXIMUM_SEND_PACKETS:
- l_Query.m_Long = 1;
- break;
- case OID_802_3_MAXIMUM_LIST_SIZE:
- l_Query.m_Long = NIC_MAX_MCAST_LIST;
- break;
- case OID_GEN_CURRENT_LOOKAHEAD:
- l_Query.m_Long = l_Adapter->m_Lookahead;
- break;
- case OID_GEN_MAXIMUM_LOOKAHEAD:
- case OID_GEN_MAXIMUM_TOTAL_SIZE:
- case OID_GEN_RECEIVE_BUFFER_SPACE:
- case OID_GEN_RECEIVE_BLOCK_SIZE:
- l_Query.m_Long = DEFAULT_PACKET_LOOKAHEAD;
- break;
- case OID_GEN_MAXIMUM_FRAME_SIZE:
- case OID_GEN_TRANSMIT_BLOCK_SIZE:
- case OID_GEN_TRANSMIT_BUFFER_SPACE:
- l_Query.m_Long = l_Adapter->m_MTU;
- break;
- case OID_PNP_CAPABILITIES:
- do
- {
- PNDIS_PNP_CAPABILITIES pPNPCapabilities;
- PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
- if (p_BufferLength >= sizeof (NDIS_PNP_CAPABILITIES))
- {
- pPNPCapabilities = (PNDIS_PNP_CAPABILITIES) (p_Buffer);
- //
- // Setting up the buffer to be returned
- // to the Protocol above the Passthru miniport
- //
- pPMstruct = &pPNPCapabilities->WakeUpCapabilities;
- pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
- pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
- pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
- }
- l_QueryLength = sizeof (NDIS_PNP_CAPABILITIES);
- }
- while (FALSE);
- break;
- case OID_PNP_QUERY_POWER:
- break;
- // Required OIDs that we don't support
- case OID_GEN_SUPPORTED_GUIDS:
- case OID_GEN_MEDIA_CAPABILITIES:
- case OID_TCP_TASK_OFFLOAD:
- case OID_FFP_SUPPORT:
- l_Status = NDIS_STATUS_INVALID_OID;
- break;
- // Optional stats OIDs
- case OID_GEN_DIRECTED_BYTES_XMIT:
- case OID_GEN_DIRECTED_FRAMES_XMIT:
- case OID_GEN_MULTICAST_BYTES_XMIT:
- case OID_GEN_MULTICAST_FRAMES_XMIT:
- case OID_GEN_BROADCAST_BYTES_XMIT:
- case OID_GEN_BROADCAST_FRAMES_XMIT:
- case OID_GEN_DIRECTED_BYTES_RCV:
- case OID_GEN_DIRECTED_FRAMES_RCV:
- case OID_GEN_MULTICAST_BYTES_RCV:
- case OID_GEN_MULTICAST_FRAMES_RCV:
- case OID_GEN_BROADCAST_BYTES_RCV:
- case OID_GEN_BROADCAST_FRAMES_RCV:
- l_Status = NDIS_STATUS_INVALID_OID;
- break;
- //===================================================================
- // Not Handled
- //===================================================================
- default:
- DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter), p_OID));
- l_Status = NDIS_STATUS_INVALID_OID;
- break;
- }
- if (l_Status != NDIS_STATUS_SUCCESS)
- ;
- else if (l_QueryLength > p_BufferLength)
- {
- l_Status = NDIS_STATUS_INVALID_LENGTH;
- *p_BytesNeeded = l_QueryLength;
- }
- else
- NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr,
- (*p_BytesWritten = l_QueryLength));
- return l_Status;
- }
- NDIS_STATUS AdapterModify
- (IN NDIS_HANDLE p_AdapterContext,
- IN NDIS_OID p_OID,
- IN PVOID p_Buffer,
- IN ULONG p_BufferLength,
- OUT PULONG p_BytesRead,
- OUT PULONG p_BytesNeeded)
- {
- TapAdapterQueryPointer l_Query = (TapAdapterQueryPointer) p_Buffer;
- TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
- NDIS_STATUS l_Status = NDIS_STATUS_INVALID_OID;
- ULONG l_Long;
- switch (p_OID)
- {
- //==================================================================
- // Device Info
- //==================================================================
- case OID_802_3_MULTICAST_LIST:
- DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n",
- NAME (l_Adapter)));
- *p_BytesNeeded = sizeof (ETH_ADDR);
- *p_BytesRead = p_BufferLength;
- if (p_BufferLength % sizeof (ETH_ADDR))
- l_Status = NDIS_STATUS_INVALID_LENGTH;
- else if (p_BufferLength > sizeof (MC_LIST))
- {
- l_Status = NDIS_STATUS_MULTICAST_FULL;
- *p_BytesNeeded = sizeof (MC_LIST);
- }
- else
- {
- NdisAcquireSpinLock (&l_Adapter->m_MCLock);
- NdisZeroMemory(&l_Adapter->m_MCList, sizeof (MC_LIST));
-
- NdisMoveMemory(&l_Adapter->m_MCList,
- p_Buffer,
- p_BufferLength);
- l_Adapter->m_MCListSize = p_BufferLength / sizeof (ETH_ADDR);
-
- NdisReleaseSpinLock (&l_Adapter->m_MCLock);
- l_Status = NDIS_STATUS_SUCCESS;
- }
- break;
- case OID_GEN_CURRENT_PACKET_FILTER:
- l_Status = NDIS_STATUS_INVALID_LENGTH;
- *p_BytesNeeded = 4;
- if (p_BufferLength >= sizeof (ULONG))
- {
- DEBUGP
- (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n",
- NAME (l_Adapter), l_Query->m_Long));
- l_Status = NDIS_STATUS_SUCCESS;
- *p_BytesRead = sizeof (ULONG);
- }
- break;
- case OID_GEN_CURRENT_LOOKAHEAD:
- if (p_BufferLength < sizeof (ULONG))
- {
- l_Status = NDIS_STATUS_INVALID_LENGTH;
- *p_BytesNeeded = 4;
- }
- else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD
- || l_Query->m_Long <= 0)
- {
- l_Status = NDIS_STATUS_INVALID_DATA;
- }
- else
- {
- DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n",
- NAME (l_Adapter), l_Query->m_Long));
- l_Adapter->m_Lookahead = l_Query->m_Long;
- l_Status = NDIS_STATUS_SUCCESS;
- *p_BytesRead = sizeof (ULONG);
- }
- break;
- case OID_GEN_NETWORK_LAYER_ADDRESSES:
- l_Status = NDIS_STATUS_SUCCESS;
- *p_BytesRead = *p_BytesNeeded = 0;
- break;
- case OID_GEN_TRANSPORT_HEADER_OFFSET:
- l_Status = NDIS_STATUS_SUCCESS;
- *p_BytesRead = *p_BytesNeeded = 0;
- break;
- case OID_PNP_SET_POWER:
- do
- {
- NDIS_DEVICE_POWER_STATE NewDeviceState;
- NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) p_Buffer);
- switch (NewDeviceState)
- {
- case NdisDeviceStateD0:
- l_Adapter->m_DeviceState = '0';
- break;
- case NdisDeviceStateD1:
- l_Adapter->m_DeviceState = '1';
- break;
- case NdisDeviceStateD2:
- l_Adapter->m_DeviceState = '2';
- break;
- case NdisDeviceStateD3:
- l_Adapter->m_DeviceState = '3';
- break;
- default:
- l_Adapter->m_DeviceState = '?';
- break;
- }
- l_Status = NDIS_STATUS_FAILURE;
- //
- // Check for invalid length
- //
- if (p_BufferLength < sizeof (NDIS_DEVICE_POWER_STATE))
- {
- l_Status = NDIS_STATUS_INVALID_LENGTH;
- break;
- }
- if (NewDeviceState > NdisDeviceStateD0)
- {
- l_Adapter->m_InterfaceIsRunning = FALSE;
- DEBUGP (("[%s] Power management device state OFF\n",
- NAME (l_Adapter)));
- }
- else
- {
- l_Adapter->m_InterfaceIsRunning = TRUE;
- DEBUGP (("[%s] Power management device state ON\n",
- NAME (l_Adapter)));
- }
- l_Status = NDIS_STATUS_SUCCESS;
- }
- while (FALSE);
- if (l_Status == NDIS_STATUS_SUCCESS)
- {
- *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE);
- *p_BytesNeeded = 0;
- }
- else
- {
- *p_BytesRead = 0;
- *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
- }
- break;
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- l_Status = NDIS_STATUS_SUCCESS;
- *p_BytesRead = *p_BytesNeeded = 0;
- break;
- default:
- DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter),
- p_OID));
- l_Status = NDIS_STATUS_INVALID_OID;
- *p_BytesRead = *p_BytesNeeded = 0;
- break;
- }
- return l_Status;
- }
- // checksum code for ICMPv6 packet, taken from dhcp.c / udp_checksum
- // see RFC 4443, 2.3, and RFC 2460, 8.1
- USHORT
- icmpv6_checksum (const UCHAR *buf,
- const int len_icmpv6,
- const UCHAR *saddr6,
- const UCHAR *daddr6)
- {
- USHORT word16;
- ULONG sum = 0;
- int i;
- // make 16 bit words out of every two adjacent 8 bit words and
- // calculate the sum of all 16 bit words
- for (i = 0; i < len_icmpv6; i += 2){
- word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_icmpv6) ? (buf[i+1] & 0xFF) : 0);
- sum += word16;
- }
- // add the IPv6 pseudo header which contains the IP source and destination addresses
- for (i = 0; i < 16; i += 2){
- word16 =((saddr6[i] << 8) & 0xFF00) + (saddr6[i+1] & 0xFF);
- sum += word16;
- }
- for (i = 0; i < 16; i += 2){
- word16 =((daddr6[i] << 8) & 0xFF00) + (daddr6[i+1] & 0xFF);
- sum += word16;
- }
- // the next-header number and the length of the ICMPv6 packet
- sum += (USHORT) IPPROTO_ICMPV6 + (USHORT) len_icmpv6;
- // keep only the last 16 bits of the 32 bit calculated sum and add the carries
- while (sum >> 16)
- sum = (sum & 0xFFFF) + (sum >> 16);
- // Take the one's complement of sum
- return ((USHORT) ~sum);
- }
- // check IPv6 packet for "is this an IPv6 Neighbor Solicitation that
- // the tap driver needs to answer?"
- // see RFC 4861 4.3 for the different cases
- static IPV6ADDR IPV6_NS_TARGET_MCAST =
- { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x08 };
- static IPV6ADDR IPV6_NS_TARGET_UNICAST =
- { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 };
- BOOLEAN
- HandleIPv6NeighborDiscovery( TapAdapterPointer p_Adapter, UCHAR * m_Data )
- {
- const ETH_HEADER * e = (ETH_HEADER *) m_Data;
- const IPV6HDR *ipv6 = (IPV6HDR *) (m_Data + sizeof (ETH_HEADER));
- const ICMPV6_NS * icmpv6_ns = (ICMPV6_NS *) (m_Data + sizeof (ETH_HEADER) + sizeof (IPV6HDR));
- ICMPV6_NA_PKT *na;
- USHORT icmpv6_len, icmpv6_csum;
- // we don't really care about the destination MAC address here
- // - it's either a multicast MAC, or the userland destination MAC
- // but since the TAP driver is point-to-point, all packets are "for us"
- // IPv6 target address must be ff02::1::ff00:8 (multicast for
- // initial NS) or fe80::1 (unicast for recurrent NUD)
- if ( memcmp( ipv6->daddr, IPV6_NS_TARGET_MCAST,
- sizeof(IPV6ADDR) ) != 0 &&
- memcmp( ipv6->daddr, IPV6_NS_TARGET_UNICAST,
- sizeof(IPV6ADDR) ) != 0 )
- {
- return FALSE; // wrong target address
- }
- // IPv6 Next-Header must be ICMPv6
- if ( ipv6->nexthdr != IPPROTO_ICMPV6 )
- {
- return FALSE; // wrong next-header
- }
- // ICMPv6 type+code must be 135/0 for NS
- if ( icmpv6_ns->type != ICMPV6_TYPE_NS ||
- icmpv6_ns->code != ICMPV6_CODE_0 )
- {
- return FALSE; // wrong ICMPv6 type
- }
- // ICMPv6 target address must be fe80::8 (magic)
- if ( memcmp( icmpv6_ns->target_addr, IPV6_NS_TARGET_UNICAST,
- sizeof(IPV6ADDR) ) != 0 )
- {
- return FALSE; // not for us
- }
- // packet identified, build magic response packet
- na = (ICMPV6_NA_PKT *) MemAlloc (sizeof (ICMPV6_NA_PKT), TRUE);
- if ( !na ) return FALSE;
- //------------------------------------------------
- // Initialize Neighbour Advertisement reply packet
- //------------------------------------------------
- // ethernet header
- na->eth.proto = htons(ETH_P_IPV6);
- COPY_MAC(na->eth.dest, p_Adapter->m_MAC);
- COPY_MAC(na->eth.src, p_Adapter->m_TapToUser.dest);
- // IPv6 header
- na->ipv6.version_prio = ipv6->version_prio;
- NdisMoveMemory( na->ipv6.flow_lbl, ipv6->flow_lbl,
- sizeof(na->ipv6.flow_lbl) );
- icmpv6_len = sizeof(ICMPV6_NA_PKT) - sizeof(ETH_HEADER) - sizeof(IPV6HDR);
- na->ipv6.payload_len = htons(icmpv6_len);
- na->ipv6.nexthdr = IPPROTO_ICMPV6;
- na->ipv6.hop_limit = 255;
- NdisMoveMemory( na->ipv6.saddr, IPV6_NS_TARGET_UNICAST,
- sizeof(IPV6ADDR) );
- NdisMoveMemory( na->ipv6.daddr, ipv6->saddr,
- sizeof(IPV6ADDR) );
- // ICMPv6
- na->icmpv6.type = ICMPV6_TYPE_NA;
- na->icmpv6.code = ICMPV6_CODE_0;
- na->icmpv6.checksum = 0;
- na->icmpv6.rso_bits = 0x60; // Solicited + Override
- NdisZeroMemory( na->icmpv6.reserved, sizeof(na->icmpv6.reserved) );
- NdisMoveMemory( na->icmpv6.target_addr, IPV6_NS_TARGET_UNICAST,
- sizeof(IPV6ADDR) );
- // ICMPv6 option "Target Link Layer Address"
- na->icmpv6.opt_type = ICMPV6_OPTION_TLLA;
- na->icmpv6.opt_length = ICMPV6_LENGTH_TLLA;
- COPY_MAC( na->icmpv6.target_macaddr, p_Adapter->m_TapToUser.dest );
- // calculate and set checksum
- icmpv6_csum = icmpv6_checksum ( (UCHAR*) &(na->icmpv6),
- icmpv6_len,
- na->ipv6.saddr,
- na->ipv6.daddr );
- na->icmpv6.checksum = htons( icmpv6_csum );
- DUMP_PACKET ("HandleIPv6NeighborDiscovery",
- (unsigned char *) na,
- sizeof (ICMPV6_NA_PKT));
- InjectPacketDeferred (p_Adapter, (UCHAR *) na, sizeof (ICMPV6_NA_PKT));
- MemFree (na, sizeof (ICMPV6_NA_PKT));
- return TRUE; // all fine
- }
- //====================================================================
- // Adapter Transmission
- //====================================================================
- NDIS_STATUS
- AdapterTransmit (IN NDIS_HANDLE p_AdapterContext,
- IN PNDIS_PACKET p_Packet,
- IN UINT p_Flags)
- {
- TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
- ULONG l_Index = 0, l_PacketLength = 0;
- UINT l_BufferLength = 0;
- PIRP l_IRP;
- TapPacketPointer l_PacketBuffer;
- PNDIS_BUFFER l_NDIS_Buffer;
- PUCHAR l_Buffer;
- PVOID result;
- NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength);
- //====================================================
- // Here we abandon the transmission attempt if any of
- // the parameters is wrong or memory allocation fails
- // but we do not indicate failure. The packet is
- // silently dropped.
- //====================================================
- if (l_PacketLength < ETHERNET_HEADER_SIZE || l_PacketLength > 65535)
- goto exit_fail;
- else if (!l_Adapter->m_Extension.m_TapOpens || !l_Adapter->m_MediaState)
- goto exit_success; // Nothing is bound to the TAP device
- if (NdisAllocateMemoryWithTag (&l_PacketBuffer,
- TAP_PACKET_SIZE (l_PacketLength),
- '5PAT') != NDIS_STATUS_SUCCESS)
- goto exit_no_resources;
- if (l_PacketBuffer == NULL)
- goto exit_no_resources;
- l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK);
- //===========================
- // Reassemble packet contents
- //===========================
- __try
- {
- l_Index = 0;
- while (l_NDIS_Buffer && l_Index < l_PacketLength)
- {
- ULONG newlen;
- NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer,
- &l_BufferLength);
- newlen = l_Index + l_BufferLength;
- if (newlen > l_PacketLength)
- {
- NOTE_ERROR ();
- goto no_queue; /* overflow */
- }
- NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer,
- l_BufferLength);
- l_Index = newlen;
- NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer);
- }
- if (l_Index != l_PacketLength)
- {
- NOTE_ERROR ();
- goto no_queue; /* underflow */
- }
- DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength);
- //=====================================================
- // If IPv4 packet, check whether or not packet
- // was truncated.
- //=====================================================
- #if PACKET_TRUNCATION_CHECK
- IPv4PacketSizeVerify (l_PacketBuffer->m_Data, l_PacketLength, FALSE, "TX", &l_Adapter->m_TxTrunc);
- #endif
- //=====================================================
- // Are we running in DHCP server masquerade mode?
- //
- // If so, catch both DHCP requests and ARP queries
- // to resolve the address of our virtual DHCP server.
- //=====================================================
- if (l_Adapter->m_dhcp_enabled)
- {
- const ETH_HEADER *eth = (ETH_HEADER *) l_PacketBuffer->m_Data;
- const IPHDR *ip = (IPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER));
- const UDPHDR *udp = (UDPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR));
- // ARP packet?
- if (l_PacketLength == sizeof (ARP_PACKET)
- && eth->proto == htons (ETH_P_ARP)
- && l_Adapter->m_dhcp_server_arp)
- {
- if (ProcessARP (l_Adapter,
- (PARP_PACKET) l_PacketBuffer->m_Data,
- l_Adapter->m_dhcp_addr,
- l_Adapter->m_dhcp_server_ip,
- ~0,
- l_Adapter->m_dhcp_server_mac))
- goto no_queue;
- }
- // DHCP packet?
- else if (l_PacketLength >= sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP)
- && eth->proto == htons (ETH_P_IP)
- && ip->version_len == 0x45 // IPv4, 20 byte header
- && ip->protocol == IPPROTO_UDP
- && udp->dest == htons (BOOTPS_PORT))
- {
- const DHCP *dhcp = (DHCP *) (l_PacketBuffer->m_Data
- + sizeof (ETH_HEADER)
- + sizeof (IPHDR)
- + sizeof (UDPHDR));
- const int optlen = l_PacketLength
- - sizeof (ETH_HEADER)
- - sizeof (IPHDR)
- - sizeof (UDPHDR)
- - sizeof (DHCP);
- if (optlen > 0) // we must have at least one DHCP option
- {
- if (ProcessDHCP (l_Adapter, eth, ip, udp, dhcp, optlen))
- goto no_queue;
- }
- else
- goto no_queue;
- }
- }
- //===============================================
- // In Point-To-Point mode, check to see whether
- // packet is ARP (handled) or IPv4 (sent to app).
- // IPv6 packets are inspected for neighbour discovery
- // (to be handled locally), and the rest is forwarded
- // all other protocols are dropped
- //===============================================
- if (l_Adapter->m_tun)
- {
- ETH_HEADER *e;
- if (l_PacketLength < ETHERNET_HEADER_SIZE)
- goto no_queue;
- e = (ETH_HEADER *) l_PacketBuffer->m_Data;
- switch (ntohs (e->proto))
- {
- case ETH_P_ARP:
- // Make sure that packet is the
- // right size for ARP.
- if (l_PacketLength != sizeof (ARP_PACKET))
- goto no_queue;
- ProcessARP (l_Adapter,
- (PARP_PACKET) l_PacketBuffer->m_Data,
- l_Adapter->m_localIP,
- l_Adapter->m_remoteNetwork,
- l_Adapter->m_remoteNetmask,
- l_Adapter->m_TapToUser.dest);
- default:
- goto no_queue;
- case ETH_P_IP:
- // Make sure that packet is large
- // enough to be IPv4.
- if (l_PacketLength
- < ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)
- goto no_queue;
- // Only accept directed packets,
- // not broadcasts.
- if (memcmp (e, &l_Adapter->m_TapToUser, ETHERNET_HEADER_SIZE))
- goto no_queue;
- // Packet looks like IPv4, queue it.
- l_PacketBuffer->m_SizeFlags |= TP_TUN;
- break;
- case ETH_P_IPV6:
- // make sure that packet is large
- // enough to be IPv6
- if (l_PacketLength
- < ETHERNET_HEADER_SIZE + IPV6_HEADER_SIZE)
- goto no_queue;
- // broadcasts and multicasts are handled specially
- // (to be implemented)
- // neighbor discovery packets to fe80::8 are special
- // OpenVPN sets this next-hop to signal "handled by tapdrv"
- if ( HandleIPv6NeighborDiscovery( l_Adapter,
- l_PacketBuffer->m_Data ))
- {
- goto no_queue;
- }
- // Packet looks like IPv6, queue it :-)
- l_PacketBuffer->m_SizeFlags |= TP_TUN;
- }
- }
- //===============================================
- // Push packet onto queue to wait for read from
- // userspace.
- //===============================================
- NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- result = NULL;
- if (IS_UP (l_Adapter))
- result = QueuePush (l_Adapter->m_Extension.m_PacketQueue, l_PacketBuffer);
- NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- if ((TapPacketPointer) result != l_PacketBuffer)
- {
- // adapter receive overrun
- INCREMENT_STAT (l_Adapter->m_TxErr);
- goto no_queue;
- }
- else
- {
- INCREMENT_STAT (l_Adapter->m_Tx);
- }
- //============================================================
- // Cycle through IRPs and packets, try to satisfy each pending
- // IRP with a queued packet.
- //============================================================
- while (TRUE)
- {
- l_IRP = NULL;
- l_PacketBuffer = NULL;
- NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- if (IS_UP (l_Adapter)
- && QueueCount (l_Adapter->m_Extension.m_PacketQueue)
- && QueueCount (l_Adapter->m_Extension.m_IrpQueue))
- {
- l_IRP = (PIRP) QueuePop (l_Adapter->m_Extension.m_IrpQueue);
- l_PacketBuffer = (TapPacketPointer)
- QueuePop (l_Adapter->m_Extension.m_PacketQueue);
- }
- NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1);
- if (l_IRP && l_PacketBuffer)
- {
- CompleteIRP (l_IRP,
- l_PacketBuffer,
- IO_NETWORK_INCREMENT);
- }
- else
- break;
- }
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- }
- return NDIS_STATUS_SUCCESS;
- no_queue:
- NdisFreeMemory (l_PacketBuffer,
- TAP_PACKET_SIZE (l_PacketLength),
- 0);
-
- exit_success:
- return NDIS_STATUS_SUCCESS;
-
- exit_fail:
- return NDIS_STATUS_FAILURE;
- exit_no_resources:
- return NDIS_STATUS_RESOURCES;
- }
- //======================================================================
- // Hooks for catching TAP device IRP's.
- //======================================================================
- DRIVER_DISPATCH TapDeviceHook;
- NTSTATUS
- TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP)
- {
- TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
- PIO_STACK_LOCATION l_IrpSp;
- NTSTATUS l_Status = STATUS_SUCCESS;
- BOOLEAN accessible;
- l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP);
- p_IRP->IoStatus.Status = STATUS_SUCCESS;
- p_IRP->IoStatus.Information = 0;
- if (!l_Adapter || l_Adapter->m_Extension.m_Halt)
- {
- DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n",
- (int)l_IrpSp->MajorFunction));
- if (l_IrpSp->MajorFunction == IRP_MJ_CLOSE)
- {
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
- else
- {
- p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- return STATUS_NO_SUCH_DEVICE;
- }
- }
- switch (l_IrpSp->MajorFunction)
- {
- //===========================================================
- // Ioctl call handlers
- //===========================================================
- case IRP_MJ_DEVICE_CONTROL:
- {
- switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode)
- {
- case TAP_WIN_IOCTL_GET_MAC:
- {
- if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
- >= sizeof (MACADDR))
- {
- COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer,
- l_Adapter->m_MAC);
- p_IRP->IoStatus.Information = sizeof (MACADDR);
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
- }
- break;
- }
- case TAP_WIN_IOCTL_GET_VERSION:
- {
- const ULONG size = sizeof (ULONG) * 3;
- if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
- >= size)
- {
- ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
- = TAP_DRIVER_MAJOR_VERSION;
- ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1]
- = TAP_DRIVER_MINOR_VERSION;
- ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2]
- #if DBG
- = 1;
- #else
- = 0;
- #endif
- p_IRP->IoStatus.Information = size;
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
- }
- break;
- }
- case TAP_WIN_IOCTL_GET_MTU:
- {
- const ULONG size = sizeof (ULONG) * 1;
- if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
- >= size)
- {
- ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
- = l_Adapter->m_MTU;
- p_IRP->IoStatus.Information = size;
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
- }
- break;
- }
- case TAP_WIN_IOCTL_GET_INFO:
- {
- char state[16];
- if (l_Adapter->m_InterfaceIsRunning)
- state[0] = 'A';
- else
- state[0] = 'a';
- if (l_Adapter->m_Extension.m_TapIsRunning)
- state[1] = 'T';
- else
- state[1] = 't';
- state[2] = l_Adapter->m_DeviceState;
- if (l_Adapter->m_MediaStateAlwaysConnected)
- state[3] = 'C';
- else
- state[3] = 'c';
- state[4] = '\0';
- p_IRP->IoStatus.Status = l_Status = RtlStringCchPrintfExA (
- ((LPTSTR) (p_IRP->AssociatedIrp.SystemBuffer)),
- l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
- NULL,
- NULL,
- STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
- #if PACKET_TRUNCATION_CHECK
- "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d,%d] Rx=[%d,%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]",
- #else
- "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]",
- #endif
- state,
- g_LastErrorFilename,
- g_LastErrorLineNumber,
- (int)l_Adapter->m_Extension.m_NumTapOpens,
- (int)l_Adapter->m_Tx,
- (int)l_Adapter->m_TxErr,
- #if PACKET_TRUNCATION_CHECK
- (int)l_Adapter->m_TxTrunc,
- #endif
- (int)l_Adapter->m_Rx,
- (int)l_Adapter->m_RxErr,
- #if PACKET_TRUNCATION_CHECK
- (int)l_Adapter->m_RxTrunc,
- #endif
- (int)l_Adapter->m_Extension.m_IrpQueue->size,
- (int)l_Adapter->m_Extension.m_IrpQueue->max_size,
- (int)IRP_QUEUE_SIZE,
- (int)l_Adapter->m_Extension.m_PacketQueue->size,
- (int)l_Adapter->m_Extension.m_PacketQueue->max_size,
- (int)PACKET_QUEUE_SIZE,
- (int)l_Adapter->m_Extension.m_InjectQueue->size,
- (int)l_Adapter->m_Extension.m_InjectQueue->max_size,
- (int)INJECT_QUEUE_SIZE
- );
- p_IRP->IoStatus.Information
- = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
- break;
- }
- #if DBG
- case TAP_WIN_IOCTL_GET_LOG_LINE:
- {
- if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer,
- l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength))
- p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
- else
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information
- = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
- break;
- }
- #endif
- case TAP_WIN_IOCTL_CONFIG_TUN:
- {
- if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
- (sizeof (IPADDR) * 3))
- {
- MACADDR dest;
- l_Adapter->m_tun = FALSE;
- GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1);
- l_Adapter->m_localIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
- l_Adapter->m_remoteNetwork = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
- l_Adapter->m_remoteNetmask = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2];
- // sanity check on network/netmask
- if ((l_Adapter->m_remoteNetwork & l_Adapter->m_remoteNetmask) != l_Adapter->m_remoteNetwork)
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- break;
- }
- COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC);
- COPY_MAC (l_Adapter->m_TapToUser.dest, dest);
- COPY_MAC (l_Adapter->m_UserToTap.src, dest);
- COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC);
- l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP);
- l_Adapter->m_UserToTap_IPv6 = l_Adapter->m_UserToTap;
- l_Adapter->m_UserToTap_IPv6.proto = htons(ETH_P_IPV6);
- l_Adapter->m_tun = TRUE;
- CheckIfDhcpAndTunMode (l_Adapter);
- p_IRP->IoStatus.Information = 1; // Simple boolean value
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- }
-
- break;
- }
- case TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT: // Obsoleted by TAP_WIN_IOCTL_CONFIG_TUN
- {
- if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
- (sizeof (IPADDR) * 2))
- {
- MACADDR dest;
- l_Adapter->m_tun = FALSE;
- GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1);
- l_Adapter->m_localIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
- l_Adapter->m_remoteNetwork = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
- l_Adapter->m_remoteNetmask = ~0;
- COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC);
- COPY_MAC (l_Adapter->m_TapToUser.dest, dest);
- COPY_MAC (l_Adapter->m_UserToTap.src, dest);
- COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC);
- l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP);
- l_Adapter->m_UserToTap_IPv6 = l_Adapter->m_UserToTap;
- l_Adapter->m_UserToTap_IPv6.proto = htons(ETH_P_IPV6);
- l_Adapter->m_tun = TRUE;
- CheckIfDhcpAndTunMode (l_Adapter);
- p_IRP->IoStatus.Information = 1; // Simple boolean value
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- }
-
- break;
- }
- case TAP_WIN_IOCTL_SET_MEDIA_STATUS:
- {
- if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
- (sizeof (ULONG) * 1))
- {
- ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0];
- SetMediaStatus (l_Adapter, (BOOLEAN) parm);
- p_IRP->IoStatus.Information = 1;
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- }
- break;
- }
- case TAP_WIN_IOCTL_CONFIG_DHCP_MASQ:
- {
- if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
- (sizeof (IPADDR) * 4))
- {
- l_Adapter->m_dhcp_enabled = FALSE;
- l_Adapter->m_dhcp_server_arp = FALSE;
- l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
- // Adapter IP addr / netmask
- l_Adapter->m_dhcp_addr =
- ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
- l_Adapter->m_dhcp_netmask =
- ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
- // IP addr of DHCP masq server
- l_Adapter->m_dhcp_server_ip =
- ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2];
- // Lease time in seconds
- l_Adapter->m_dhcp_lease_time =
- ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[3];
- GenerateRelatedMAC (l_Adapter->m_dhcp_server_mac, l_Adapter->m_MAC, 2);
- l_Adapter->m_dhcp_enabled = TRUE;
- l_Adapter->m_dhcp_server_arp = TRUE;
- CheckIfDhcpAndTunMode (l_Adapter);
- p_IRP->IoStatus.Information = 1; // Simple boolean value
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- }
-
- break;
- }
- case TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT:
- {
- if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength <=
- DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
- && l_Adapter->m_dhcp_enabled)
- {
- l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
- NdisMoveMemory (l_Adapter->m_dhcp_user_supplied_options_buffer,
- p_IRP->AssociatedIrp.SystemBuffer,
- l_IrpSp->Parameters.DeviceIoControl.InputBufferLength);
-
- l_Adapter->m_dhcp_user_supplied_options_buffer_len =
- l_IrpSp->Parameters.DeviceIoControl.InputBufferLength;
- p_IRP->IoStatus.Information = 1; // Simple boolean value
- }
- else
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- }
-
- break;
- }
- default:
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- break;
- }
- }
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- //===========================================================
- // User mode thread issued a read request on the tap device
- // If there are packets waiting to be read, then the request
- // will be satisfied here. If not, then the request will be
- // queued and satisfied by any packet that is not used to
- // satisfy requests ahead of it.
- //===========================================================
- case IRP_MJ_READ:
- {
- TapPacketPointer l_PacketBuffer;
- BOOLEAN pending = FALSE;
- // Save IRP-accessible copy of buffer length
- p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length;
- if (p_IRP->MdlAddress == NULL)
- {
- DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- p_IRP->IoStatus.Information = 0;
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- else if ((p_IRP->AssociatedIrp.SystemBuffer =
- MmGetSystemAddressForMdlSafe
- (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
- {
- DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
- p_IRP->IoStatus.Information = 0;
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- else if (!l_Adapter->m_InterfaceIsRunning)
- {
- DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- //==================================
- // Can we provide immediate service?
- //==================================
- l_PacketBuffer = NULL;
- NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- if (IS_UP (l_Adapter)
- && QueueCount (l_Adapter->m_Extension.m_PacketQueue)
- && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0)
- {
- l_PacketBuffer = (TapPacketPointer)
- QueuePop (l_Adapter->m_Extension.m_PacketQueue);
- }
- NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- if (l_PacketBuffer)
- {
- l_Status = CompleteIRP (p_IRP,
- l_PacketBuffer,
- IO_NO_INCREMENT);
- break;
- }
- //=============================
- // Attempt to pend read request
- //=============================
- NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- if (IS_UP (l_Adapter)
- && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP)
- {
- IoSetCancelRoutine (p_IRP, CancelIRPCallback);
- l_Status = STATUS_PENDING;
- IoMarkIrpPending (p_IRP);
- pending = TRUE;
- }
- NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
- if (pending)
- break;
- // Can't queue anymore IRP's
- DEBUGP (("[%s] TAP [%s] read IRP overrun\n",
- NAME (l_Adapter), l_Adapter->m_Extension.m_TapName));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- //==============================================================
- // User mode issued a WriteFile request on the TAP file handle.
- // The request will always get satisfied here. The call may
- // fail if there are too many pending packets (queue full).
- //==============================================================
- case IRP_MJ_WRITE:
- {
- if (p_IRP->MdlAddress == NULL)
- {
- DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
- p_IRP->IoStatus.Information = 0;
- }
- else if ((p_IRP->AssociatedIrp.SystemBuffer =
- MmGetSystemAddressForMdlSafe
- (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
- {
- DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
- p_IRP->IoStatus.Information = 0;
- }
- else if (!l_Adapter->m_InterfaceIsRunning)
- {
- DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- }
- else if (!l_Adapter->m_tun && ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
- {
- __try
- {
- p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
- DUMP_PACKET ("IRP_MJ_WRITE ETH",
- (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
- l_IrpSp->Parameters.Write.Length);
- //=====================================================
- // If IPv4 packet, check whether or not packet
- // was truncated.
- //=====================================================
- #if PACKET_TRUNCATION_CHECK
- IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
- l_IrpSp->Parameters.Write.Length,
- FALSE,
- "RX",
- &l_Adapter->m_RxTrunc);
- #endif
- NdisMEthIndicateReceive
- (l_Adapter->m_MiniportAdapterHandle,
- (NDIS_HANDLE) l_Adapter,
- (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
- ETHERNET_HEADER_SIZE,
- (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE,
- l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE,
- l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE);
-
- NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
- p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- }
- }
- else if (l_Adapter->m_tun && ((l_IrpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
- {
- __try
- {
- ETH_HEADER * p_UserToTap = &l_Adapter->m_UserToTap;
- // for IPv6, need to use ethernet header with IPv6 proto
- if ( IPH_GET_VER( ((IPHDR*) p_IRP->AssociatedIrp.SystemBuffer)->version_len) == 6 )
- {
- p_UserToTap = &l_Adapter->m_UserToTap_IPv6;
- }
- p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
- DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
- p_UserToTap,
- (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
- l_IrpSp->Parameters.Write.Length);
- //=====================================================
- // If IPv4 packet, check whether or not packet
- // was truncated.
- //=====================================================
- #if PACKET_TRUNCATION_CHECK
- IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
- l_IrpSp->Parameters.Write.Length,
- TRUE,
- "RX",
- &l_Adapter->m_RxTrunc);
- #endif
- NdisMEthIndicateReceive
- (l_Adapter->m_MiniportAdapterHandle,
- (NDIS_HANDLE) l_Adapter,
- (unsigned char *) p_UserToTap,
- sizeof (ETH_HEADER),
- (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
- l_IrpSp->Parameters.Write.Length,
- l_IrpSp->Parameters.Write.Length);
- NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
- p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n",
- NAME (l_Adapter)));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- }
- }
- else
- {
- DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
- NAME (l_Adapter),
- l_IrpSp->Parameters.Write.Length));
- NOTE_ERROR ();
- p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE;
- p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
- }
- if (l_Status == STATUS_SUCCESS)
- INCREMENT_STAT (l_Adapter->m_Rx);
- else
- INCREMENT_STAT (l_Adapter->m_RxErr);
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- //--------------------------------------------------------------
- // User mode thread has called CreateFile() on the tap device
- //--------------------------------------------------------------
- case IRP_MJ_CREATE:
- {
- BOOLEAN succeeded = FALSE;
- BOOLEAN mutex_succeeded;
- DEBUGP
- (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n",
- NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens));
- ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
- if (mutex_succeeded)
- {
- if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens)
- {
- ResetTapAdapterState (l_Adapter);
- l_Adapter->m_Extension.m_TapOpens = 1;
- succeeded = TRUE;
- }
- if (succeeded)
- {
- INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens);
- p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
- p_IRP->IoStatus.Information = 0;
- }
- else
- {
- DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
- NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- }
- RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
- }
- else
- {
- DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
- NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- }
-
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
-
- //-----------------------------------------------------------
- // User mode thread called CloseHandle() on the tap device
- //-----------------------------------------------------------
- case IRP_MJ_CLOSE:
- {
- BOOLEAN mutex_succeeded;
- DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n",
- NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION));
- ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
- if (mutex_succeeded)
- {
- l_Adapter->m_Extension.m_TapOpens = 0;
- ResetTapAdapterState (l_Adapter);
- FlushQueues (&l_Adapter->m_Extension);
- SetMediaStatus (l_Adapter, FALSE);
- RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
- }
- else
- {
- DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
- NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- }
-
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- //------------------
- // Strange Request
- //------------------
- default:
- {
- //NOTE_ERROR ();
- p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- break;
- }
- }
- return l_Status;
- }
- //=============================================================
- // CompleteIRP is normally called with an adapter -> userspace
- // network packet and an IRP (Pending I/O request) from userspace.
- //
- // The IRP will normally represent a queued overlapped read
- // operation from userspace that is in a wait state.
- //
- // Use the ethernet packet to satisfy the IRP.
- //=============================================================
- NTSTATUS
- CompleteIRP (IN PIRP p_IRP,
- IN TapPacketPointer p_PacketBuffer,
- IN CCHAR PriorityBoost)
- {
- NTSTATUS l_Status = STATUS_UNSUCCESSFUL;
- int offset;
- int len;
- MYASSERT (p_IRP);
- MYASSERT (p_PacketBuffer);
- IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine
- //-------------------------------------------
- // While p_PacketBuffer always contains a
- // full ethernet packet, including the
- // ethernet header, in point-to-point mode,
- // we only want to return the IPv4
- // component.
- //-------------------------------------------
- if (p_PacketBuffer->m_SizeFlags & TP_TUN)
- {
- offset = ETHERNET_HEADER_SIZE;
- len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE;
- }
- else
- {
- offset = 0;
- len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK);
- }
- if (len < 0 || (int) p_IRP->IoStatus.Information < len)
- {
- p_IRP->IoStatus.Information = 0;
- p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
- NOTE_ERROR ();
- }
- else
- {
- p_IRP->IoStatus.Information = len;
- p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
- __try
- {
- NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer,
- p_PacketBuffer->m_Data + offset,
- len);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- NOTE_ERROR ();
- p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
- p_IRP->IoStatus.Information = 0;
- }
- }
- __try
- {
- NdisFreeMemory (p_PacketBuffer,
- TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK),
- 0);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- }
-
- if (l_Status == STATUS_SUCCESS)
- {
- IoCompleteRequest (p_IRP, PriorityBoost);
- }
- else
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- return l_Status;
- }
- //==============================================
- // IRPs get cancelled for a number of reasons.
- //
- // The TAP device could be closed by userspace
- // when there are still pending read operations.
- //
- // The user could disable the TAP adapter in the
- // network connections control panel, while the
- // device is still open by a process.
- //==============================================
- VOID
- CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject,
- IN PIRP p_IRP)
- {
- TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
- CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE);
- }
- VOID
- CancelIRP (TapExtensionPointer p_Extension,
- IN PIRP p_IRP,
- BOOLEAN callback)
- {
- BOOLEAN exists = FALSE;
- MYASSERT (p_IRP);
- if (p_Extension)
- {
- NdisAcquireSpinLock (&p_Extension->m_QueueLock);
- exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP);
- NdisReleaseSpinLock (&p_Extension->m_QueueLock);
- }
- else
- exists = TRUE;
- if (exists)
- {
- IoSetCancelRoutine (p_IRP, NULL);
- p_IRP->IoStatus.Status = STATUS_CANCELLED;
- p_IRP->IoStatus.Information = 0;
- }
-
- if (callback)
- IoReleaseCancelSpinLock (p_IRP->CancelIrql);
- if (exists)
- IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
- }
- //===========================================
- // Exhaust packet, IRP, and injection queues.
- //===========================================
- VOID
- FlushQueues (TapExtensionPointer p_Extension)
- {
- PIRP l_IRP;
- TapPacketPointer l_PacketBuffer;
- InjectPacketPointer l_InjectBuffer;
- int n_IRP=0, n_Packet=0, n_Inject=0;
- MYASSERT (p_Extension);
- MYASSERT (p_Extension->m_TapDevice);
- while (TRUE)
- {
- NdisAcquireSpinLock (&p_Extension->m_QueueLock);
- l_IRP = QueuePop (p_Extension->m_IrpQueue);
- NdisReleaseSpinLock (&p_Extension->m_QueueLock);
- if (l_IRP)
- {
- ++n_IRP;
- CancelIRP (NULL, l_IRP, FALSE);
- }
- else
- break;
- }
- while (TRUE)
- {
- NdisAcquireSpinLock (&p_Extension->m_QueueLock);
- l_PacketBuffer = QueuePop (p_Extension->m_PacketQueue);
- NdisReleaseSpinLock (&p_Extension->m_QueueLock);
- if (l_PacketBuffer)
- {
- ++n_Packet;
- MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK));
- }
- else
- break;
- }
- while (TRUE)
- {
- NdisAcquireSpinLock (&p_Extension->m_InjectLock);
- l_InjectBuffer = QueuePop (p_Extension->m_InjectQueue);
- NdisReleaseSpinLock (&p_Extension->m_InjectLock);
- if (l_InjectBuffer)
- {
- ++n_Inject;
- INJECT_PACKET_FREE(l_InjectBuffer);
- }
- else
- break;
- }
- DEBUGP ((
- "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d] n_Inject=[%d,%d,%d]\n",
- p_Extension->m_TapName,
- n_IRP,
- p_Extension->m_IrpQueue->max_size,
- IRP_QUEUE_SIZE,
- n_Packet,
- p_Extension->m_PacketQueue->max_size,
- PACKET_QUEUE_SIZE,
- n_Inject,
- p_Extension->m_InjectQueue->max_size,
- INJECT_QUEUE_SIZE
- ));
- }
- //===================================================
- // Tell Windows whether the TAP device should be
- // considered "connected" or "disconnected".
- //===================================================
- VOID
- SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state)
- {
- if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected)
- {
- if (state)
- NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
- NDIS_STATUS_MEDIA_CONNECT, NULL, 0);
- else
- NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
- NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0);
- NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle);
- p_Adapter->m_MediaState = state;
- }
- }
- //======================================================
- // If DHCP mode is used together with tun
- // mode, consider the fact that the P2P remote subnet
- // might enclose the DHCP masq server address.
- //======================================================
- VOID
- CheckIfDhcpAndTunMode (TapAdapterPointer p_Adapter)
- {
- if (p_Adapter->m_tun && p_Adapter->m_dhcp_enabled)
- {
- if ((p_Adapter->m_dhcp_server_ip & p_Adapter->m_remoteNetmask) == p_Adapter->m_remoteNetwork)
- {
- COPY_MAC (p_Adapter->m_dhcp_server_mac, p_Adapter->m_TapToUser.dest);
- p_Adapter->m_dhcp_server_arp = FALSE;
- }
- }
- }
- //===================================================
- // Generate an ARP reply message for specific kinds
- // ARP queries.
- //===================================================
- BOOLEAN
- ProcessARP (TapAdapterPointer p_Adapter,
- const PARP_PACKET src,
- const IPADDR adapter_ip,
- const IPADDR ip_network,
- const IPADDR ip_netmask,
- const MACADDR mac)
- {
- //-----------------------------------------------
- // Is this the kind of packet we are looking for?
- //-----------------------------------------------
- if (src->m_Proto == htons (ETH_P_ARP)
- && MAC_EQUAL (src->m_MAC_Source, p_Adapter->m_MAC)
- && MAC_EQUAL (src->m_ARP_MAC_Source, p_Adapter->m_MAC)
- && MAC_EQUAL (src->m_MAC_Destination, p_Adapter->m_MAC_Broadcast)
- && src->m_ARP_Operation == htons (ARP_REQUEST)
- && src->m_MAC_AddressType == htons (MAC_ADDR_TYPE)
- && src->m_MAC_AddressSize == sizeof (MACADDR)
- && src->m_PROTO_AddressType == htons (ETH_P_IP)
- && src->m_PROTO_AddressSize == sizeof (IPADDR)
- && src->m_ARP_IP_Source == adapter_ip
- && (src->m_ARP_IP_Destination & ip_netmask) == ip_network
- && src->m_ARP_IP_Destination != adapter_ip)
- {
- ARP_PACKET *arp = (ARP_PACKET *) MemAlloc (sizeof (ARP_PACKET), TRUE);
- if (arp)
- {
- //----------------------------------------------
- // Initialize ARP reply fields
- //----------------------------------------------
- arp->m_Proto = htons (ETH_P_ARP);
- arp->m_MAC_AddressType = htons (MAC_ADDR_TYPE);
- arp->m_PROTO_AddressType = htons (ETH_P_IP);
- arp->m_MAC_AddressSize = sizeof (MACADDR);
- arp->m_PROTO_AddressSize = sizeof (IPADDR);
- arp->m_ARP_Operation = htons (ARP_REPLY);
- //----------------------------------------------
- // ARP addresses
- //----------------------------------------------
- COPY_MAC (arp->m_MAC_Source, mac);
- COPY_MAC (arp->m_MAC_Destination, p_Adapter->m_MAC);
- COPY_MAC (arp->m_ARP_MAC_Source, mac);
- COPY_MAC (arp->m_ARP_MAC_Destination, p_Adapter->m_MAC);
- arp->m_ARP_IP_Source = src->m_ARP_IP_Destination;
- arp->m_ARP_IP_Destination = adapter_ip;
- DUMP_PACKET ("ProcessARP",
- (unsigned char *) arp,
- sizeof (ARP_PACKET));
- InjectPacketDeferred (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET));
- MemFree (arp, sizeof (ARP_PACKET));
- }
- return TRUE;
- }
- else
- return FALSE;
- }
- //===============================================================
- // Used in cases where internally generated packets such as
- // ARP or DHCP replies must be returned to the kernel, to be
- // seen as an incoming packet "arriving" on the interface.
- //===============================================================
- // Defer packet injection till IRQL < DISPATCH_LEVEL
- VOID
- InjectPacketDeferred (TapAdapterPointer p_Adapter,
- UCHAR *packet,
- const unsigned int len)
- {
- InjectPacketPointer l_InjectBuffer;
- PVOID result;
- if (NdisAllocateMemoryWithTag (&l_InjectBuffer,
- INJECT_PACKET_SIZE (len),
- 'IPAT') == NDIS_STATUS_SUCCESS)
- {
- l_InjectBuffer->m_Size = len;
- NdisMoveMemory (l_InjectBuffer->m_Data, packet, len);
- NdisAcquireSpinLock (&p_Adapter->m_Extension.m_InjectLock);
- result = QueuePush (p_Adapter->m_Extension.m_InjectQueue, l_InjectBuffer);
- NdisReleaseSpinLock (&p_Adapter->m_Extension.m_InjectLock);
- if (result)
- KeInsertQueueDpc (&p_Adapter->m_Extension.m_InjectDpc, p_Adapter, NULL);
- else
- INJECT_PACKET_FREE(l_InjectBuffer);
- }
- }
- // Handle the injection of previously deferred packets
- VOID
- InjectPacketDpc(KDPC *Dpc,
- PVOID DeferredContext,
- PVOID SystemArgument1,
- PVOID SystemArgument2)
- {
- InjectPacketPointer l_InjectBuffer;
- TapAdapterPointer l_Adapter = (TapAdapterPointer)SystemArgument1;
- while (TRUE)
- {
- NdisAcquireSpinLock (&l_Adapter->m_Extension.m_InjectLock);
- l_InjectBuffer = QueuePop (l_Adapter->m_Extension.m_InjectQueue);
- NdisReleaseSpinLock (&l_Adapter->m_Extension.m_InjectLock);
- if (l_InjectBuffer)
- {
- InjectPacketNow(l_Adapter, l_InjectBuffer->m_Data, l_InjectBuffer->m_Size);
- INJECT_PACKET_FREE(l_InjectBuffer);
- }
- else
- break;
- }
- }
- // Do packet injection now
- VOID
- InjectPacketNow (TapAdapterPointer p_Adapter,
- UCHAR *packet,
- const unsigned int len)
- {
- MYASSERT (len >= ETHERNET_HEADER_SIZE);
- __try
- {
- //------------------------------------------------------------
- // NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete
- // could potentially be called reentrantly both here and in
- // TapDeviceHook/IRP_MJ_WRITE.
- //
- // The DDK docs imply that this is okay.
- //
- // Note that reentrant behavior could only occur if the
- // non-deferred version of InjectPacket is used.
- //------------------------------------------------------------
- NdisMEthIndicateReceive
- (p_Adapter->m_MiniportAdapterHandle,
- (NDIS_HANDLE) p_Adapter,
- packet,
- ETHERNET_HEADER_SIZE,
- packet + ETHERNET_HEADER_SIZE,
- len - ETHERNET_HEADER_SIZE,
- len - ETHERNET_HEADER_SIZE);
-
- NdisMEthIndicateReceiveComplete (p_Adapter->m_MiniportAdapterHandle);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacketNow\n",
- NAME (p_Adapter)));
- NOTE_ERROR ();
- }
- }
- //===================================================================
- // Go back to default TAP mode from Point-To-Point mode.
- // Also reset (i.e. disable) DHCP Masq mode.
- //===================================================================
- VOID ResetTapAdapterState (TapAdapterPointer p_Adapter)
- {
- // Point-To-Point
- p_Adapter->m_tun = FALSE;
- p_Adapter->m_localIP = 0;
- p_Adapter->m_remoteNetwork = 0;
- p_Adapter->m_remoteNetmask = 0;
- NdisZeroMemory (&p_Adapter->m_TapToUser, sizeof (p_Adapter->m_TapToUser));
- NdisZeroMemory (&p_Adapter->m_UserToTap, sizeof (p_Adapter->m_UserToTap));
- NdisZeroMemory (&p_Adapter->m_UserToTap_IPv6, sizeof (p_Adapter->m_UserToTap_IPv6));
- // DHCP Masq
- p_Adapter->m_dhcp_enabled = FALSE;
- p_Adapter->m_dhcp_server_arp = FALSE;
- p_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
- p_Adapter->m_dhcp_addr = 0;
- p_Adapter->m_dhcp_netmask = 0;
- p_Adapter->m_dhcp_server_ip = 0;
- p_Adapter->m_dhcp_lease_time = 0;
- p_Adapter->m_dhcp_received_discover = FALSE;
- p_Adapter->m_dhcp_bad_requests = 0;
- NdisZeroMemory (p_Adapter->m_dhcp_server_mac, sizeof (MACADDR));
- }
- #if ENABLE_NONADMIN
- //===================================================================
- // Set TAP device handle to be accessible without admin privileges.
- //===================================================================
- VOID AllowNonAdmin (TapExtensionPointer p_Extension)
- {
- NTSTATUS stat;
- SECURITY_DESCRIPTOR sd;
- OBJECT_ATTRIBUTES oa;
- IO_STATUS_BLOCK isb;
- HANDLE hand = NULL;
- NdisZeroMemory (&sd, sizeof (sd));
- NdisZeroMemory (&oa, sizeof (oa));
- NdisZeroMemory (&isb, sizeof (isb));
- if (!p_Extension->m_CreatedUnicodeLinkName)
- {
- DEBUGP (("[TAP] AllowNonAdmin: UnicodeLinkName is uninitialized\n"));
- NOTE_ERROR ();
- return;
- }
- stat = RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
- if (stat != STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] AllowNonAdmin: RtlCreateSecurityDescriptor failed\n"));
- NOTE_ERROR ();
- return;
- }
- InitializeObjectAttributes (
- &oa,
- &p_Extension->m_UnicodeLinkName,
- OBJ_KERNEL_HANDLE,
- NULL,
- NULL
- );
- stat = ZwOpenFile (
- &hand,
- WRITE_DAC,
- &oa,
- &isb,
- 0,
- 0
- );
- if (stat != STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] AllowNonAdmin: ZwOpenFile failed, status=0x%08x\n", (unsigned int)stat));
- NOTE_ERROR ();
- return;
- }
- stat = ZwSetSecurityObject (hand, DACL_SECURITY_INFORMATION, &sd);
- if (stat != STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] AllowNonAdmin: ZwSetSecurityObject failed\n"));
- NOTE_ERROR ();
- return;
- }
- stat = ZwClose (hand);
- if (stat != STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] AllowNonAdmin: ZwClose failed\n"));
- NOTE_ERROR ();
- return;
- }
- DEBUGP (("[TAP] AllowNonAdmin: SUCCEEDED\n"));
- }
- #endif
- #if PACKET_TRUNCATION_CHECK
- VOID
- IPv4PacketSizeVerify (const UCHAR *data, ULONG length, BOOLEAN tun, const char *prefix, LONG *counter)
- {
- const IPHDR *ip;
- int len = length;
- if (tun)
- {
- ip = (IPHDR *) data;
- }
- else
- {
- if (length >= sizeof (ETH_HEADER))
- {
- const ETH_HEADER *eth = (ETH_HEADER *) data;
- if (eth->proto != htons (ETH_P_IP))
- return;
- ip = (IPHDR *) (data + sizeof (ETH_HEADER));
- len -= sizeof (ETH_HEADER);
- }
- else
- return;
- }
- if (len >= sizeof (IPHDR))
- {
- const int totlen = ntohs (ip->tot_len);
- DEBUGP (("[TAP] IPv4PacketSizeVerify %s len=%d totlen=%d\n", prefix, len, totlen));
- if (len != totlen)
- ++(*counter);
- }
- }
- #endif
- //======================================================================
- // End of Source
- //======================================================================
|