1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210 |
- /*
- * 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-2014 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
- */
- //
- // Include files.
- //
- #include "tap.h"
- #include <wdmsec.h> // for SDDLs
- //======================================================================
- // TAP Win32 Device I/O Callbacks
- //======================================================================
- #ifdef ALLOC_PRAGMA
- #pragma alloc_text( PAGE, TapDeviceCreate)
- #pragma alloc_text( PAGE, TapDeviceControl)
- #pragma alloc_text( PAGE, TapDeviceCleanup)
- #pragma alloc_text( PAGE, TapDeviceClose)
- #endif // ALLOC_PRAGMA
- //===================================================================
- // Go back to default TAP mode from Point-To-Point mode.
- // Also reset (i.e. disable) DHCP Masq mode.
- //===================================================================
- VOID tapResetAdapterState(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- /*
- // Point-To-Point
- Adapter->m_tun = FALSE;
- Adapter->m_localIP = 0;
- Adapter->m_remoteNetwork = 0;
- Adapter->m_remoteNetmask = 0;
- NdisZeroMemory (&Adapter->m_TapToUser, sizeof (Adapter->m_TapToUser));
- NdisZeroMemory (&Adapter->m_UserToTap, sizeof (Adapter->m_UserToTap));
- NdisZeroMemory (&Adapter->m_UserToTap_IPv6, sizeof (Adapter->m_UserToTap_IPv6));
- */
- // DHCP Masq
- /*
- Adapter->m_dhcp_enabled = FALSE;
- Adapter->m_dhcp_server_arp = FALSE;
- Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
- Adapter->m_dhcp_addr = 0;
- Adapter->m_dhcp_netmask = 0;
- Adapter->m_dhcp_server_ip = 0;
- Adapter->m_dhcp_lease_time = 0;
- Adapter->m_dhcp_received_discover = FALSE;
- Adapter->m_dhcp_bad_requests = 0;
- NdisZeroMemory (Adapter->m_dhcp_server_mac, MACADDR_SIZE);
- */
- }
- // IRP_MJ_CREATE
- NTSTATUS
- TapDeviceCreate(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp
- )
- /*++
- Routine Description:
- This routine is called by the I/O system when the device is opened.
- No action is performed other than completing the request successfully.
- Arguments:
- DeviceObject - a pointer to the object that represents the device
- that I/O is to be done on.
- Irp - a pointer to the I/O Request Packet for this request.
- Return Value:
- NT status code
- --*/
- {
- NDIS_STATUS status;
- PIO_STACK_LOCATION irpSp;// Pointer to current stack location
- PTAP_ADAPTER_CONTEXT adapter = NULL;
- PFILE_OBJECT originalFileObject;
- PAGED_CODE();
- DEBUGP (("[TAP] --> TapDeviceCreate\n"));
- irpSp = IoGetCurrentIrpStackLocation(Irp);
- //
- // Invalidate file context
- //
- irpSp->FileObject->FsContext = NULL;
- irpSp->FileObject->FsContext2 = NULL;
- //
- // Find adapter context for this device.
- // -------------------------------------
- // Returns with added reference on adapter context.
- //
- adapter = tapAdapterContextFromDeviceObject(DeviceObject);
- // Insure that adapter exists.
- ASSERT(adapter);
- if(adapter == NULL )
- {
- DEBUGP (("[TAP] release [%d.%d] open request; adapter not found\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION
- ));
- Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest( Irp, IO_NO_INCREMENT );
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
- DEBUGP(("[%s] [TAP] release [%d.%d] open request (TapFileIsOpen=%d)\n",
- MINIPORT_INSTANCE_ID(adapter),
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION,
- adapter->TapFileIsOpen
- ));
- // Enforce exclusive access
- originalFileObject = InterlockedCompareExchangePointer(
- &adapter->TapFileObject,
- irpSp->FileObject,
- NULL
- );
- if(originalFileObject == NULL)
- {
- irpSp->FileObject->FsContext = adapter; // Quick reference
- status = STATUS_SUCCESS;
- }
- else
- {
- status = STATUS_UNSUCCESSFUL;
- }
- // Release the lock.
- //tapAdapterReleaseLock(adapter,FALSE);
- if(status == STATUS_SUCCESS)
- {
- // Reset adapter state on successful open.
- tapResetAdapterState(adapter);
- adapter->TapFileIsOpen = 1; // Legacy...
- // NOTE!!! Reference added by tapAdapterContextFromDeviceObject
- // will be removed when file is closed.
- }
- else
- {
- DEBUGP (("[%s] TAP is presently unavailable (TapFileIsOpen=%d)\n",
- MINIPORT_INSTANCE_ID(adapter), adapter->TapFileIsOpen
- ));
- NOTE_ERROR();
- // Remove reference added by tapAdapterContextFromDeviceObject.
- tapAdapterContextDereference(adapter);
- }
- // Complete the IRP.
- Irp->IoStatus.Status = status;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest( Irp, IO_NO_INCREMENT );
- DEBUGP (("[TAP] <-- TapDeviceCreate; status = %8.8X\n",status));
- return status;
- }
- //===================================================
- // Tell Windows whether the TAP device should be
- // considered "connected" or "disconnected".
- //
- // Allows application control of media connect state.
- //===================================================
- VOID
- tapSetMediaConnectStatus(
- __in PTAP_ADAPTER_CONTEXT Adapter,
- __in BOOLEAN LogicalMediaState
- )
- {
- NDIS_STATUS_INDICATION statusIndication;
- NDIS_LINK_STATE linkState;
- NdisZeroMemory(&statusIndication, sizeof(NDIS_STATUS_INDICATION));
- NdisZeroMemory(&linkState, sizeof(NDIS_LINK_STATE));
- //
- // Fill in object headers
- //
- statusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
- statusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
- statusIndication.Header.Size = sizeof(NDIS_STATUS_INDICATION);
- linkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
- linkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- linkState.Header.Size = sizeof(NDIS_LINK_STATE);
- //
- // Link state buffer
- //
- if(Adapter->LogicalMediaState == TRUE)
- {
- linkState.MediaConnectState = MediaConnectStateConnected;
- }
- linkState.MediaDuplexState = MediaDuplexStateFull;
- linkState.RcvLinkSpeed = TAP_RECV_SPEED;
- linkState.XmitLinkSpeed = TAP_XMIT_SPEED;
- //
- // Fill in the status buffer
- //
- statusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
- statusIndication.SourceHandle = Adapter->MiniportAdapterHandle;
- statusIndication.DestinationHandle = NULL;
- statusIndication.RequestId = 0;
- statusIndication.StatusBuffer = &linkState;
- statusIndication.StatusBufferSize = sizeof(NDIS_LINK_STATE);
- // Fill in new media connect state.
- if ( (Adapter->LogicalMediaState != LogicalMediaState) && !Adapter->MediaStateAlwaysConnected)
- {
- Adapter->LogicalMediaState = LogicalMediaState;
- if (LogicalMediaState == TRUE)
- {
- linkState.MediaConnectState = MediaConnectStateConnected;
- DEBUGP (("[TAP] Set MediaConnectState: Connected.\n"));
- }
- else
- {
- linkState.MediaConnectState = MediaConnectStateDisconnected;
- DEBUGP (("[TAP] Set MediaConnectState: Disconnected.\n"));
- }
- }
- // Make the status indication.
- if(Adapter->Locked.AdapterState != MiniportHaltedState)
- {
- NdisMIndicateStatusEx(Adapter->MiniportAdapterHandle, &statusIndication);
- }
- }
- /*
- //======================================================
- // 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 (
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- if (Adapter->m_tun && Adapter->m_dhcp_enabled)
- {
- if ((Adapter->m_dhcp_server_ip & Adapter->m_remoteNetmask) == Adapter->m_remoteNetwork)
- {
- ETH_COPY_NETWORK_ADDRESS (Adapter->m_dhcp_server_mac, Adapter->m_TapToUser.dest);
- Adapter->m_dhcp_server_arp = FALSE;
- }
- }
- }
- */
- // IRP_MJ_DEVICE_CONTROL callback.
- NTSTATUS
- TapDeviceControl(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp
- )
- /*++
- Routine Description:
- This routine is called by the I/O system to perform a device I/O
- control function.
- Arguments:
- DeviceObject - a pointer to the object that represents the device
- that I/O is to be done on.
- Irp - a pointer to the I/O Request Packet for this request.
- Return Value:
- NT status code
- --*/
- {
- NTSTATUS ntStatus = STATUS_SUCCESS; // Assume success
- PIO_STACK_LOCATION irpSp; // Pointer to current stack location
- PTAP_ADAPTER_CONTEXT adapter = NULL;
- ULONG inBufLength; // Input buffer length
- ULONG outBufLength; // Output buffer length
- PCHAR inBuf, outBuf; // pointer to Input and output buffer
- PMDL mdl = NULL;
- PCHAR buffer = NULL;
- PAGED_CODE();
- irpSp = IoGetCurrentIrpStackLocation( Irp );
- //
- // Fetch adapter context for this device.
- // --------------------------------------
- // Adapter pointer was stashed in FsContext when handle was opened.
- //
- adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;
- ASSERT(adapter);
- inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
- outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
- if (!inBufLength || !outBufLength)
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- goto End;
- }
- //
- // Determine which I/O control code was specified.
- //
- switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
- {
- case TAP_WIN_IOCTL_GET_MAC:
- {
- if (outBufLength >= MACADDR_SIZE )
- {
- ETH_COPY_NETWORK_ADDRESS(
- Irp->AssociatedIrp.SystemBuffer,
- adapter->CurrentAddress
- );
- Irp->IoStatus.Information = MACADDR_SIZE;
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- }
- break;
- case TAP_WIN_IOCTL_GET_VERSION:
- {
- const ULONG size = sizeof (ULONG) * 3;
- if (outBufLength >= size)
- {
- ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[0]
- = TAP_DRIVER_MAJOR_VERSION;
- ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[1]
- = TAP_DRIVER_MINOR_VERSION;
- ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[2]
- #if DBG
- = 1;
- #else
- = 0;
- #endif
- Irp->IoStatus.Information = size;
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- }
- break;
- case TAP_WIN_IOCTL_GET_MTU:
- {
- const ULONG size = sizeof (ULONG) * 1;
- if (outBufLength >= size)
- {
- ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[0]
- = adapter->MtuSize;
- Irp->IoStatus.Information = size;
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- }
- break;
- // Allow ZeroTier One to get multicast memberships at the L2 level in a
- // protocol-neutral manner.
- case TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS:
- {
- if (outBufLength < TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE) {
- /* output buffer too small */
- NOTE_ERROR ();
- Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
- } else {
- char *out = (char *)Irp->AssociatedIrp.SystemBuffer;
- char *end = out + TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE;
- unsigned long i,j;
- for(i=0;i<adapter->ulMCListSize;++i) {
- if (i >= TAP_MAX_MCAST_LIST)
- break;
- for(j=0;j<6;++j)
- *(out++) = adapter->MCList[i][j];
- if (out >= end)
- break;
- }
- while (out < end)
- *(out++) = (char)0;
- Irp->IoStatus.Information = TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE;
- Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
- }
- break;
- }
- #if 0
- case TAP_WIN_IOCTL_CONFIG_TUN:
- {
- if(inBufLength >= sizeof(IPADDR)*3)
- {
- MACADDR dest;
- adapter->m_tun = FALSE;
- GenerateRelatedMAC (dest, adapter->CurrentAddress, 1);
- adapter->m_localIP = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[0];
- adapter->m_remoteNetwork = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[1];
- adapter->m_remoteNetmask = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[2];
- // Sanity check on network/netmask
- if ((adapter->m_remoteNetwork & adapter->m_remoteNetmask) != adapter->m_remoteNetwork)
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
- break;
- }
- ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.src, adapter->CurrentAddress);
- ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.dest, dest);
- ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.src, dest);
- ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.dest, adapter->CurrentAddress);
- adapter->m_TapToUser.proto = adapter->m_UserToTap.proto = htons (NDIS_ETH_TYPE_IPV4);
- adapter->m_UserToTap_IPv6 = adapter->m_UserToTap;
- adapter->m_UserToTap_IPv6.proto = htons(NDIS_ETH_TYPE_IPV6);
- adapter->m_tun = TRUE;
- CheckIfDhcpAndTunMode (adapter);
- Irp->IoStatus.Information = 1; // Simple boolean value
- DEBUGP (("[TAP] Set TUN mode.\n"));
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- break;
- case TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT:
- {
- if(inBufLength >= sizeof(IPADDR)*2)
- {
- MACADDR dest;
- adapter->m_tun = FALSE;
- GenerateRelatedMAC (dest, adapter->CurrentAddress, 1);
- adapter->m_localIP = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[0];
- adapter->m_remoteNetwork = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[1];
- adapter->m_remoteNetmask = ~0;
- ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.src, adapter->CurrentAddress);
- ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.dest, dest);
- ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.src, dest);
- ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.dest, adapter->CurrentAddress);
- adapter->m_TapToUser.proto = adapter->m_UserToTap.proto = htons (NDIS_ETH_TYPE_IPV4);
- adapter->m_UserToTap_IPv6 = adapter->m_UserToTap;
- adapter->m_UserToTap_IPv6.proto = htons(NDIS_ETH_TYPE_IPV6);
- adapter->m_tun = TRUE;
- CheckIfDhcpAndTunMode (adapter);
- Irp->IoStatus.Information = 1; // Simple boolean value
- DEBUGP (("[TAP] Set P2P mode.\n"));
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- break;
- #endif
- #if 0
- case TAP_WIN_IOCTL_CONFIG_DHCP_MASQ:
- {
- if(inBufLength >= sizeof(IPADDR)*4)
- {
- adapter->m_dhcp_enabled = FALSE;
- adapter->m_dhcp_server_arp = FALSE;
- adapter->m_dhcp_user_supplied_options_buffer_len = 0;
- // Adapter IP addr / netmask
- adapter->m_dhcp_addr =
- ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[0];
- adapter->m_dhcp_netmask =
- ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[1];
- // IP addr of DHCP masq server
- adapter->m_dhcp_server_ip =
- ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[2];
- // Lease time in seconds
- adapter->m_dhcp_lease_time =
- ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[3];
- GenerateRelatedMAC(
- adapter->m_dhcp_server_mac,
- adapter->CurrentAddress,
- 2
- );
- adapter->m_dhcp_enabled = TRUE;
- adapter->m_dhcp_server_arp = TRUE;
- CheckIfDhcpAndTunMode (adapter);
- Irp->IoStatus.Information = 1; // Simple boolean value
- DEBUGP (("[TAP] Configured DHCP MASQ.\n"));
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- break;
- case TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT:
- {
- if (inBufLength <= DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
- && adapter->m_dhcp_enabled)
- {
- adapter->m_dhcp_user_supplied_options_buffer_len = 0;
- NdisMoveMemory(
- adapter->m_dhcp_user_supplied_options_buffer,
- Irp->AssociatedIrp.SystemBuffer,
- inBufLength
- );
- adapter->m_dhcp_user_supplied_options_buffer_len =
- inBufLength;
- Irp->IoStatus.Information = 1; // Simple boolean value
- DEBUGP (("[TAP] Set DHCP OPT.\n"));
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- break;
- #endif
- #if 0
- case TAP_WIN_IOCTL_GET_INFO:
- {
- char state[16];
- // Fetch adapter (miniport) state.
- if (tapAdapterSendAndReceiveReady(adapter) == NDIS_STATUS_SUCCESS)
- state[0] = 'A';
- else
- state[0] = 'a';
- if (tapAdapterReadAndWriteReady(adapter))
- state[1] = 'T';
- else
- state[1] = 't';
- state[2] = '0' + adapter->CurrentPowerState;
- if (adapter->MediaStateAlwaysConnected)
- state[3] = 'C';
- else
- state[3] = 'c';
- state[4] = '\0';
- // BUGBUG!!! What follows, and is not yet implemented, is a real mess.
- // BUGBUG!!! Tied closely to the NDIS 5 implementation. Need to map
- // as much as possible to the NDIS 6 implementation.
- Irp->IoStatus.Status = ntStatus = RtlStringCchPrintfExA (
- ((LPTSTR) (Irp->AssociatedIrp.SystemBuffer)),
- outBufLength,
- 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)adapter->TapFileOpenCount,
- (int)(adapter->FramesTxDirected + adapter->FramesTxMulticast + adapter->FramesTxBroadcast),
- (int)adapter->TransmitFailuresOther,
- #if PACKET_TRUNCATION_CHECK
- (int)adapter->m_TxTrunc,
- #endif
- (int)adapter->m_Rx,
- (int)adapter->m_RxErr,
- #if PACKET_TRUNCATION_CHECK
- (int)adapter->m_RxTrunc,
- #endif
- (int)adapter->PendingReadIrpQueue.Count,
- (int)adapter->PendingReadIrpQueue.MaxCount,
- (int)IRP_QUEUE_SIZE, // Ignored in NDIS 6 driver...
- (int)adapter->SendPacketQueue.Count,
- (int)adapter->SendPacketQueue.MaxCount,
- (int)PACKET_QUEUE_SIZE,
- (int)0, // adapter->InjectPacketQueue.Count - Unused
- (int)0, // adapter->InjectPacketQueue.MaxCount - Unused
- (int)INJECT_QUEUE_SIZE
- );
- Irp->IoStatus.Information = outBufLength;
- // BUGBUG!!! Fail because this is not completely implemented.
- ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- }
- #endif
- #if DBG
- case TAP_WIN_IOCTL_GET_LOG_LINE:
- {
- if (GetDebugLine( (LPTSTR)Irp->AssociatedIrp.SystemBuffer,outBufLength))
- {
- Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
- }
- else
- {
- Irp->IoStatus.Status = ntStatus = STATUS_UNSUCCESSFUL;
- }
- Irp->IoStatus.Information = outBufLength;
- break;
- }
- #endif
- case TAP_WIN_IOCTL_SET_MEDIA_STATUS:
- {
- if(inBufLength >= sizeof(ULONG))
- {
- ULONG parm = ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[0];
- tapSetMediaConnectStatus (adapter, (BOOLEAN) parm);
- Irp->IoStatus.Information = 1;
- }
- else
- {
- NOTE_ERROR();
- Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- break;
- default:
- //
- // The specified I/O control code is unrecognized by this driver.
- //
- ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- break;
- }
- End:
- //
- // Finish the I/O operation by simply completing the packet and returning
- // the same status as in the packet itself.
- //
- Irp->IoStatus.Status = ntStatus;
- IoCompleteRequest( Irp, IO_NO_INCREMENT );
- return ntStatus;
- }
- // Flush the pending read IRP queue.
- VOID
- tapFlushIrpQueues(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- DEBUGP (("[TAP] tapFlushIrpQueues: Flushing %d pending read IRPs\n",
- Adapter->PendingReadIrpQueue.Count));
- tapIrpCsqFlush(&Adapter->PendingReadIrpQueue);
- }
- // IRP_MJ_CLEANUP
- NTSTATUS
- TapDeviceCleanup(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp
- )
- /*++
- Routine Description:
- Receipt of this request indicates that the last handle for a file
- object that is associated with the target device object has been closed
- (but, due to outstanding I/O requests, might not have been released).
- A driver that holds pending IRPs internally must implement a routine for
- IRP_MJ_CLEANUP. When the routine is called, the driver should cancel all
- the pending IRPs that belong to the file object identified by the IRP_MJ_CLEANUP
- call.
-
- In other words, it should cancel all the IRPs that have the same file-object
- pointer as the one supplied in the current I/O stack location of the IRP for the
- IRP_MJ_CLEANUP call. Of course, IRPs belonging to other file objects should
- not be canceled. Also, if an outstanding IRP is completed immediately, the
- driver does not have to cancel it.
- Arguments:
- DeviceObject - a pointer to the object that represents the device
- to be cleaned up.
- Irp - a pointer to the I/O Request Packet for this request.
- Return Value:
- NT status code
- --*/
- {
- NDIS_STATUS status = NDIS_STATUS_SUCCESS; // Always succeed.
- PIO_STACK_LOCATION irpSp; // Pointer to current stack location
- PTAP_ADAPTER_CONTEXT adapter = NULL;
- PAGED_CODE();
- DEBUGP (("[TAP] --> TapDeviceCleanup\n"));
- irpSp = IoGetCurrentIrpStackLocation(Irp);
- //
- // Fetch adapter context for this device.
- // --------------------------------------
- // Adapter pointer was stashed in FsContext when handle was opened.
- //
- adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;
- // Insure that adapter exists.
- ASSERT(adapter);
- if(adapter == NULL )
- {
- DEBUGP (("[TAP] release [%d.%d] cleanup request; adapter not found\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION
- ));
- }
- if(adapter != NULL )
- {
- adapter->TapFileIsOpen = 0; // Legacy...
- // Disconnect from media.
- tapSetMediaConnectStatus(adapter,FALSE);
- // Reset adapter state when cleaning up;
- tapResetAdapterState(adapter);
- // BUGBUG!!! Use RemoveLock???
- //
- // Flush pending send TAP packet queue.
- //
- tapFlushSendPacketQueue(adapter);
- ASSERT(adapter->SendPacketQueue.Count == 0);
- //
- // Flush the pending IRP queues
- //
- tapFlushIrpQueues(adapter);
- ASSERT(adapter->PendingReadIrpQueue.Count == 0);
- }
- // Complete the IRP.
- Irp->IoStatus.Status = status;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest( Irp, IO_NO_INCREMENT );
- DEBUGP (("[TAP] <-- TapDeviceCleanup; status = %8.8X\n",status));
- return status;
- }
- // IRP_MJ_CLOSE
- NTSTATUS
- TapDeviceClose(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp
- )
- /*++
- Routine Description:
- Receipt of this request indicates that the last handle of the file
- object that is associated with the target device object has been closed
- and released.
-
- All outstanding I/O requests have been completed or canceled.
- Arguments:
- DeviceObject - a pointer to the object that represents the device
- to be closed.
- Irp - a pointer to the I/O Request Packet for this request.
- Return Value:
- NT status code
- --*/
- {
- NDIS_STATUS status = NDIS_STATUS_SUCCESS; // Always succeed.
- PIO_STACK_LOCATION irpSp; // Pointer to current stack location
- PTAP_ADAPTER_CONTEXT adapter = NULL;
- PAGED_CODE();
- DEBUGP (("[TAP] --> TapDeviceClose\n"));
- irpSp = IoGetCurrentIrpStackLocation(Irp);
- //
- // Fetch adapter context for this device.
- // --------------------------------------
- // Adapter pointer was stashed in FsContext when handle was opened.
- //
- adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;
- // Insure that adapter exists.
- ASSERT(adapter);
- if(adapter == NULL )
- {
- DEBUGP (("[TAP] release [%d.%d] close request; adapter not found\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION
- ));
- }
- if(adapter != NULL )
- {
- if(adapter->TapFileObject == NULL)
- {
- // Should never happen!!!
- ASSERT(FALSE);
- }
- else
- {
- ASSERT(irpSp->FileObject->FsContext == adapter);
- ASSERT(adapter->TapFileObject == irpSp->FileObject);
- }
- adapter->TapFileObject = NULL;
- irpSp->FileObject = NULL;
- // Remove reference added by when handle was opened.
- tapAdapterContextDereference(adapter);
- }
- // Complete the IRP.
- Irp->IoStatus.Status = status;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest( Irp, IO_NO_INCREMENT );
- DEBUGP (("[TAP] <-- TapDeviceClose; status = %8.8X\n",status));
- return status;
- }
- NTSTATUS
- tapConcatenateNdisStrings(
- __inout PNDIS_STRING DestinationString,
- __in_opt PNDIS_STRING SourceString1,
- __in_opt PNDIS_STRING SourceString2,
- __in_opt PNDIS_STRING SourceString3
- )
- {
- NTSTATUS status;
- ASSERT(SourceString1 && SourceString2 && SourceString3);
- status = RtlAppendUnicodeStringToString(
- DestinationString,
- SourceString1
- );
- if(status == STATUS_SUCCESS)
- {
- status = RtlAppendUnicodeStringToString(
- DestinationString,
- SourceString2
- );
- if(status == STATUS_SUCCESS)
- {
- status = RtlAppendUnicodeStringToString(
- DestinationString,
- SourceString3
- );
- }
- }
- return status;
- }
- NTSTATUS
- tapMakeDeviceNames(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- NDIS_STATUS status;
- NDIS_STRING deviceNamePrefix = NDIS_STRING_CONST("\\Device\\");
- NDIS_STRING tapNameSuffix = NDIS_STRING_CONST(".tap");
- // Generate DeviceName from NetCfgInstanceId.
- Adapter->DeviceName.Buffer = Adapter->DeviceNameBuffer;
- Adapter->DeviceName.MaximumLength = sizeof(Adapter->DeviceNameBuffer);
- status = tapConcatenateNdisStrings(
- &Adapter->DeviceName,
- &deviceNamePrefix,
- &Adapter->NetCfgInstanceId,
- &tapNameSuffix
- );
- if(status == STATUS_SUCCESS)
- {
- NDIS_STRING linkNamePrefix = NDIS_STRING_CONST("\\DosDevices\\Global\\");
- Adapter->LinkName.Buffer = Adapter->LinkNameBuffer;
- Adapter->LinkName.MaximumLength = sizeof(Adapter->LinkNameBuffer);
- status = tapConcatenateNdisStrings(
- &Adapter->LinkName,
- &linkNamePrefix,
- &Adapter->NetCfgInstanceId,
- &tapNameSuffix
- );
- }
- return status;
- }
- NDIS_STATUS
- CreateTapDevice(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- NDIS_STATUS status;
- NDIS_DEVICE_OBJECT_ATTRIBUTES deviceAttribute;
- PDRIVER_DISPATCH dispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
- DEBUGP (("[TAP] version [%d.%d] creating tap device: %wZ\n",
- TAP_DRIVER_MAJOR_VERSION,
- TAP_DRIVER_MINOR_VERSION,
- &Adapter->NetCfgInstanceId));
- // Generate DeviceName and LinkName from NetCfgInstanceId.
- status = tapMakeDeviceNames(Adapter);
- if (NT_SUCCESS(status))
- {
- DEBUGP (("[TAP] DeviceName: %wZ\n",&Adapter->DeviceName));
- DEBUGP (("[TAP] LinkName: %wZ\n",&Adapter->LinkName));
- // Initialize dispatch table.
- NdisZeroMemory(dispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));
- dispatchTable[IRP_MJ_CREATE] = TapDeviceCreate;
- dispatchTable[IRP_MJ_CLEANUP] = TapDeviceCleanup;
- dispatchTable[IRP_MJ_CLOSE] = TapDeviceClose;
- dispatchTable[IRP_MJ_READ] = TapDeviceRead;
- dispatchTable[IRP_MJ_WRITE] = TapDeviceWrite;
- dispatchTable[IRP_MJ_DEVICE_CONTROL] = TapDeviceControl;
- //
- // Create a device object and register dispatch handlers
- //
- NdisZeroMemory(&deviceAttribute, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES));
- deviceAttribute.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
- deviceAttribute.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
- deviceAttribute.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES);
- deviceAttribute.DeviceName = &Adapter->DeviceName;
- deviceAttribute.SymbolicName = &Adapter->LinkName;
- deviceAttribute.MajorFunctions = &dispatchTable[0];
- //deviceAttribute.ExtensionSize = sizeof(FILTER_DEVICE_EXTENSION);
- #if ENABLE_NONADMIN
- if(Adapter->AllowNonAdmin)
- {
- //
- // SDDL_DEVOBJ_SYS_ALL_WORLD_RWX_RES_RWX allows the kernel and system complete
- // control over the device. By default the admin can access the entire device,
- // but cannot change the ACL (the admin must take control of the device first)
- //
- // Everyone else, including "restricted" or "untrusted" code can read or write
- // to the device. Traversal beneath the device is also granted (removing it
- // would only effect storage devices, except if the "bypass-traversal"
- // privilege was revoked).
- //
- deviceAttribute.DefaultSDDLString = &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX;
- }
- #endif
- status = NdisRegisterDeviceEx(
- Adapter->MiniportAdapterHandle,
- &deviceAttribute,
- &Adapter->DeviceObject,
- &Adapter->DeviceHandle
- );
- }
- ASSERT(NT_SUCCESS(status));
- if (NT_SUCCESS(status))
- {
- // Set TAP device flags.
- (Adapter->DeviceObject)->Flags &= ~DO_BUFFERED_IO;
- (Adapter->DeviceObject)->Flags |= DO_DIRECT_IO;;
- //========================
- // Finalize initialization
- //========================
- Adapter->TapDeviceCreated = TRUE;
- DEBUGP (("[%wZ] successfully created TAP device [%wZ]\n",
- &Adapter->NetCfgInstanceId,
- &Adapter->DeviceName
- ));
- }
- DEBUGP (("[TAP] <-- CreateTapDevice; status = %8.8X\n",status));
- return status;
- }
- //
- // DestroyTapDevice is called from AdapterHalt and NDIS miniport
- // is in Halted state. Prior to entering the Halted state the
- // miniport would have passed through the Pausing and Paused
- // states. These miniport states have responsibility for waiting
- // until NDIS network operations have completed.
- //
- VOID
- DestroyTapDevice(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- DEBUGP (("[TAP] --> DestroyTapDevice; Adapter: %wZ\n",
- &Adapter->NetCfgInstanceId));
- //
- // Let clients know we are shutting down
- //
- Adapter->TapDeviceCreated = FALSE;
- //
- // Flush pending send TAP packet queue.
- //
- tapFlushSendPacketQueue(Adapter);
- ASSERT(Adapter->SendPacketQueue.Count == 0);
- //
- // Flush IRP queues. Wait for pending I/O. Etc.
- // --------------------------------------------
- // Exhaust IRP and packet queues. Any pending IRPs will
- // be cancelled, causing user-space to get this error
- // on overlapped reads:
- //
- // ERROR_OPERATION_ABORTED, code=995
- //
- // "The I/O operation has been aborted because of either a
- // thread exit or an application request."
- //
- // It's important that user-space close the device handle
- // when this code is returned, so that when we finally
- // do a NdisMDeregisterDeviceEx, the device reference count
- // is 0. Otherwise the driver will not unload even if the
- // the last adapter has been halted.
- //
- // The act of flushing the queues at this point should result in the user-mode
- // application closing the adapter's device handle. Closing the handle will
- // result in the TapDeviceCleanup call being made, followed by the a call to
- // the TapDeviceClose callback.
- //
- tapFlushIrpQueues(Adapter);
- ASSERT(Adapter->PendingReadIrpQueue.Count == 0);
- //
- // Deregister the Win32 device.
- // ----------------------------
- // When a driver calls NdisDeregisterDeviceEx, the I/O manager deletes the
- // target device object if there are no outstanding references to it. However,
- // if any outstanding references remain, the I/O manager marks the device
- // object as "delete pending" and deletes the device object when the references
- // are finally released.
- //
- if(Adapter->DeviceHandle)
- {
- DEBUGP (("[TAP] Calling NdisDeregisterDeviceEx\n"));
- NdisDeregisterDeviceEx(Adapter->DeviceHandle);
- }
- Adapter->DeviceHandle = NULL;
- DEBUGP (("[TAP] <-- DestroyTapDevice\n"));
- }
|