Example #1
0
// Read the next packet from the driver
bool SuGetNextPacket(SU_ADAPTER *a, void **buf, UINT *size)
{
    // Validate arguments
    if (a == NULL || buf == NULL || size == NULL)
    {
        return false;
    }

    if (a->Halt)
    {
        return false;
    }

    while (true)
    {
        if (a->CurrentPacketCount < SL_NUM_PACKET(a->GetBuffer))
        {
            // There are still packets that have been already read
            *size = SL_SIZE_OF_PACKET(a->GetBuffer, a->CurrentPacketCount);
            *buf = Malloc(*size);
            Copy(*buf, SL_ADDR_OF_PACKET(a->GetBuffer, a->CurrentPacketCount), *size);

            // Increment the packet number
            a->CurrentPacketCount++;

            return true;
        }
        else
        {
            // Read the next packet from the driver
            if (SuGetPacketsFromDriver(a) == false)
            {
                return false;
            }

            if (SL_NUM_PACKET(a->GetBuffer) == 0)
            {
                // Packet is not received yet
                *buf = NULL;
                *size = 0;
                return true;
            }

            a->CurrentPacketCount = 0;
        }
    }
}
Example #2
0
// Write the next packet to the driver
bool SuPutPacket(SU_ADAPTER *a, void *buf, UINT size)
{
    // Validate arguments
    if (a == NULL)
    {
        return false;
    }
    if (a->Halt)
    {
        return false;
    }
    if (size > MAX_PACKET_SIZE)
    {
        return false;
    }

    // First, examine whether the current buffer is full
    if ((SL_NUM_PACKET(a->PutBuffer) >= SL_MAX_PACKET_EXCHANGE) ||
            (buf == NULL && SL_NUM_PACKET(a->PutBuffer) != 0))
    {
        // Write all current packets to the driver
        if (SuPutPacketsToDriver(a) == false)
        {
            return false;
        }

        SL_NUM_PACKET(a->PutBuffer) = 0;
    }

    // Add the next packet to the buffer
    if (buf != NULL)
    {
        UINT i = SL_NUM_PACKET(a->PutBuffer);
        SL_NUM_PACKET(a->PutBuffer)++;

        SL_SIZE_OF_PACKET(a->PutBuffer, i) = size;
        Copy(SL_ADDR_OF_PACKET(a->PutBuffer, i), buf, size);

        Free(buf);
    }

    return true;
}
Example #3
0
// Write procedure of the device
NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp)
{
	SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
	NTSTATUS ret = STATUS_UNSUCCESSFUL;
	IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
	UINT ret_size = 0;

	if (dev->IsBasicDevice == false)
	{
		// Adapter device
		SL_FILE *f = irp_stack->FileObject->FsContext;

		if (irp_stack->Parameters.Write.Length == SL_EXCHANGE_BUFFER_SIZE)
		{
			UCHAR *buf = irp->UserBuffer;

			if (dev->Halting || dev->Adapter->Halt || buf == NULL)
			{
				// Halting
			}
			else
			{
				// Write the packet
				MDL *mdl;
				UINT num = SL_NUM_PACKET(buf);

				mdl = IoAllocateMdl(buf, SL_EXCHANGE_BUFFER_SIZE, false, false, NULL);
				if (mdl != NULL)
				{
					MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
				}

				ret = true;
				ret_size = SL_EXCHANGE_BUFFER_SIZE;

				if (num >= 1 && num <= SL_MAX_PACKET_EXCHANGE)
				{
					UINT i, j;
					NET_BUFFER_LIST *nbl_head = NULL;
					NET_BUFFER_LIST *nbl_tail = NULL;
					UINT num_packets = 0;
					NDIS_HANDLE adapter_handle = NULL;

					SlLock(f->Adapter->Lock);

					if (f->Adapter->NumPendingSendPackets <= SL_MAX_PACKET_QUEUED)
					{
						// Admit to send only if the number of packets being transmitted does not exceed the specified limit
						adapter_handle = f->Adapter->AdapterHandle;
					}

					if (adapter_handle != NULL)
					{
						// Lock the file list which opens the same adapter
						SlLockList(dev->FileList);
						for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
						{
							SL_FILE *other = SL_LIST_DATA(dev->FileList, j);

							if (other != f)
							{
								// Lock the receive queue of other file lists
								SlLock(other->RecvLock);

								other->SetEventFlag = false;
							}
						}

						for (i = 0;i < num;i++)
						{
							UINT packet_size = SL_SIZE_OF_PACKET(buf, i);
							UCHAR *packet_buf;
							NET_BUFFER_LIST *nbl = NULL;
							bool ok = false;

							if (packet_size > SL_MAX_PACKET_SIZE)
							{
								packet_size = SL_MAX_PACKET_SIZE;
							}
							else if (packet_size < SL_PACKET_HEADER_SIZE)
							{
								packet_size = SL_PACKET_HEADER_SIZE;
							}

							packet_buf = (UCHAR *)SL_ADDR_OF_PACKET(buf, i);

							for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
							{
								SL_FILE *other = SL_LIST_DATA(dev->FileList, j);

								if (other != f)
								{
									// Insert into the receive queue of the other file lists
									if (other->NumRecvPackets < SL_MAX_PACKET_QUEUED)
									{
										SL_PACKET *q = SlMalloc(sizeof(SL_PACKET));

										SlCopy(q->Data, packet_buf, packet_size);
										q->Size = packet_size;
										q->Next = NULL;

										if (other->RecvPacketHead == NULL)
										{
											other->RecvPacketHead = q;
										}
										else
										{
											other->RecvPacketTail->Next = q;
										}

										other->RecvPacketTail = q;

										other->NumRecvPackets++;

										other->SetEventFlag = true;
									}
								}
							}

							// Allocate a new NET_BUFFER_LIST
							if (f->NetBufferListPool != NULL)
							{
								nbl = NdisAllocateNetBufferList(f->NetBufferListPool, 16, 0);

								if (nbl != NULL)
								{
									nbl->SourceHandle = adapter_handle;
								}
							}

							if (nbl != NULL)
							{
								// Get the NET_BUFFER from the NET_BUFFER_LIST
								NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);

								NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;

								if (nb != NULL && OK(NdisRetreatNetBufferDataStart(nb, packet_size, 0, NULL)))
								{
									// Buffer copy
									UCHAR *dst = NdisGetDataBuffer(nb, packet_size, NULL, 1, 0);

									if (dst != NULL)
									{
										SlCopy(dst, packet_buf, packet_size);

										ok = true;
									}
									else
									{
										NdisAdvanceNetBufferDataStart(nb, packet_size, false, NULL);
									}
								}
							}

							if (ok == false)
							{
								if (nbl != NULL)
								{
									NdisFreeNetBufferList(nbl);
								}
							}
							else
							{
								if (nbl_head == NULL)
								{
									nbl_head = nbl;
								}

								if (nbl_tail != NULL)
								{
									NET_BUFFER_LIST_NEXT_NBL(nbl_tail) = nbl;
								}

								nbl_tail = nbl;

								*((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl)) = f;

								num_packets++;
							}
						}

						for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
						{
							SL_FILE *other = SL_LIST_DATA(dev->FileList, j);

							if (other != f)
							{
								// Release the receive queue of other file lists
								SlUnlock(other->RecvLock);

								// Set an event
								if (other->SetEventFlag)
								{
									SlSet(other->Event);
								}
							}
						}
						SlUnlockList(dev->FileList);

						if (nbl_head != NULL)
						{
							InterlockedExchangeAdd(&f->NumSendingPacketets, num_packets);
							InterlockedExchangeAdd(&f->Adapter->NumPendingSendPackets, num_packets);

							SlUnlock(f->Adapter->Lock);

							NdisSendNetBufferLists(adapter_handle, nbl_head, 0, 0);
						}
						else
						{
							SlUnlock(f->Adapter->Lock);
						}
					}
					else
					{
						SlUnlock(f->Adapter->Lock);
					}
				}

				if (mdl != NULL)
				{
					MmUnlockPages(mdl);
					IoFreeMdl(mdl);
				}
			}
		}
	}

	irp->IoStatus.Information = ret_size;
	irp->IoStatus.Status = ret;
	IoCompleteRequest(irp, IO_NO_INCREMENT);

	return ret;
}
Example #4
0
// Read procedure of the device
NTSTATUS SlDeviceReadProc(DEVICE_OBJECT *device_object, IRP *irp)
{
	SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
	NTSTATUS ret = STATUS_UNSUCCESSFUL;
	UINT ret_size = 0;
	IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);

	if (dev->IsBasicDevice)
	{
		// Return the adapter list in the case of basic device
		if (irp_stack->Parameters.Read.Length >= sizeof(SL_ADAPTER_INFO_LIST))
		{
			SL_ADAPTER_INFO_LIST *dst = irp->UserBuffer;

			if (dst != NULL)
			{
				MDL *mdl;

				mdl = IoAllocateMdl(dst, irp_stack->Parameters.Read.Length, false, false, NULL);
				if (mdl != NULL)
				{
					MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
				}

				SlZero(dst, sizeof(SL_ADAPTER_INFO_LIST));

				dst->Signature = SL_SIGNATURE;
				dst->SeLowVersion = SL_VER;
				dst->EnumCompleted = sl->IsEnumCompleted ? 8 : 1;

				SlLockList(sl->AdapterList);
				{
					UINT i;

					dst->NumAdapters = MIN(SL_LIST_NUM(sl->AdapterList), SL_MAX_ADAPTER_INFO_LIST_ENTRY);

					for (i = 0;i < dst->NumAdapters;i++)
					{
						SL_ADAPTER *a = SL_LIST_DATA(sl->AdapterList, i);
						SL_ADAPTER_INFO *d = &dst->Adapters[i];

						d->MtuSize = a->MtuSize;
						SlCopy(d->MacAddress, a->MacAddress, 6);
						SlCopy(d->AdapterId, a->AdapterId, sizeof(a->AdapterId));
						strcpy(d->FriendlyName, a->FriendlyName);
					}
				}
				SlUnlockList(sl->AdapterList);

				ret_size = sizeof(SL_ADAPTER_INFO);
				ret = STATUS_SUCCESS;

				if (mdl != NULL)
				{
					MmUnlockPages(mdl);
					IoFreeMdl(mdl);
				}
			}
		}
	}
	else
	{
		// Adapter device
		SL_FILE *f = irp_stack->FileObject->FsContext;

		if (irp_stack->Parameters.Read.Length == SL_EXCHANGE_BUFFER_SIZE)
		{
			UCHAR *buf = irp->UserBuffer;

			if (dev->Halting || f->Adapter->Halt || buf == NULL)
			{
				// Halting
			}
			else
			{
				UINT num = 0;
				bool left = true;
				MDL *mdl;
				
				mdl = IoAllocateMdl(buf, SL_EXCHANGE_BUFFER_SIZE, false, false, NULL);
				if (mdl != NULL)
				{
					MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
				}

				// Lock the receive queue
				SlLock(f->RecvLock);
				{
					while (true)
					{
						SL_PACKET *q;
						if (num >= SL_MAX_PACKET_EXCHANGE)
						{
							if (f->RecvPacketHead == NULL)
							{
								left = false;
							}
							break;
						}
						q = f->RecvPacketHead;
						if (q != NULL)
						{
							f->RecvPacketHead = f->RecvPacketHead->Next;
							q->Next = NULL;
							f->NumRecvPackets--;

							if (f->RecvPacketHead == NULL)
							{
								f->RecvPacketTail = NULL;
							}
						}
						else
						{
							left = false;
							break;
						}
						SL_SIZE_OF_PACKET(buf, num) = q->Size;
						SlCopy(SL_ADDR_OF_PACKET(buf, num), q->Data, q->Size);
						num++;
						SlFree(q);
					}
				}
				SlUnlock(f->RecvLock);

				if (mdl != NULL)
				{
					MmUnlockPages(mdl);
					IoFreeMdl(mdl);
				}

				SL_NUM_PACKET(buf) = num;
				SL_LEFT_FLAG(buf) = left;

				if (left == false)
				{
					SlReset(f->Event);
				}
				else
				{
					SlSet(f->Event);
				}

				ret = STATUS_SUCCESS;
				ret_size = SL_EXCHANGE_BUFFER_SIZE;
			}
		}
	}

	irp->IoStatus.Status = ret;
	irp->IoStatus.Information = ret_size;
	IoCompleteRequest(irp, IO_NO_INCREMENT);

	return ret;
}