⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapdrvr.c

📁 一个Windows下的Linux专用虚拟机
💻 C
📖 第 1 页 / 共 5 页
字号:
	  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;}//====================================================================//                               Adapter Transmission//====================================================================NDIS_STATUSAdapterTransmit (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_BufferLength = 0, l_PacketLength = 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 or IPv4 (if neither, then drop).    //===============================================    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;	  }      }    //===============================================    // 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.//======================================================================NTSTATUSTapDeviceHook (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_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_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_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_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]",#else		"State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%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,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -