Send/Recive Multicast UDP with TDI client

All,

I am writing a TDI client driver to run on WinXP, SP2. One of the
requirements of the driver is to send/rcv multicast packets. The driver
works in conjunction with a WSK app that adds a local interface to the
multicast cast group. Within the TDI client driver we are doing the
following:

  1. Binding to the IPMULTICAST device using the IP address of the local
    interface plus an arbitary port number.
  2. To send the datagram, we are using TdiBuildSendDatagram with the
    SendDatagramInfo set with the address of the multicast add/port.

When the driver calls IoCallDriver to send the datagram, it returns with and
invalid parameter error.

So the question is: can someone please tell me how to send a UDP datagram to
a multicast group from within a TDI client driver?

TIA,
Jim

> 1. Binding to the IPMULTICAST device

What is it? should be \Device\Udp or \Device\Ip

Group membership is only important for multicast receives - for sends, just sendto() a datagram to a group address same way as to point address.

Another important socket option is multicast TTL, which influences sends.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

In the last TDI based multicast sender/receiver I wrote the process was
simply:

  1. Open an Address Object on \Device\Udp
  2. Using IOCTL_TCP_SET_INFORMATION_EX set the address object options
    MCASTIF, MCASTTTL, and MCASTLOOP.
  3. Using IOCTL_TCP_SET_INFORMATION_EX join the group with address object
    option ADD_MCAST.

The values of the various options and how to form a
IOCTL_TCP_SET_INFORMATION_EX can be found by looking at the WSHSMPLE sample
from older DDKs as well as other demonstration code sources. AFAIK none of
it is ‘documented’ by MSFT other than by inference from WSHSMPLE and
(believe it or not!) very ancient WFW3.11 (Snowball) TDIVXD & Winsock Helper
samples. Another good source of information was the MS Research IPv6
source-code for NT4 which was published and may still be downloadable from
MSR.

I should warn you, however, that recently I have found that this MCAST TDI
Client which worked just fine for ages including on Vista/LH now does not
work correctly on Windows 7. Go figure. I have no intentions of diagnosing
why but instead plan to re-write it as Winsock Kernel (finally) and just
kiss TDI goodnight.

Good Luck,
Dave Cattley

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of JimmyJ
Sent: Thursday, November 05, 2009 10:44 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Send/Recive Multicast UDP with TDI client

All,

I am writing a TDI client driver to run on WinXP, SP2. One of the
requirements of the driver is to send/rcv multicast packets. The driver
works in conjunction with a WSK app that adds a local interface to the
multicast cast group. Within the TDI client driver we are doing the
following:

  1. Binding to the IPMULTICAST device using the IP address of the local
    interface plus an arbitary port number.
  2. To send the datagram, we are using TdiBuildSendDatagram with the
    SendDatagramInfo set with the address of the multicast add/port.

When the driver calls IoCallDriver to send the datagram, it returns with and

invalid parameter error.

So the question is: can someone please tell me how to send a UDP datagram to

a multicast group from within a TDI client driver?

TIA,
Jim


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> The values of the various options and how to form a

IOCTL_TCP_SET_INFORMATION_EX can be found by looking at the WSHSMPLE sample
from older DDKs

…or rev.eng. of the OS-provided WSHTCPIP.DLL which is the full version of WSHSMPLE.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Thanks for the replies.

I fixed the UDP send problem so we’re good there but now I am trying to
receive data from a multicast group.

To receive, the driver is doing the following:

  • Bind to the UDP stack
  • Using the Local IP Add and the Multicast group address, the driver
    attempts to join the MCast group.

When the driver send the IOCTL_TCP_SET_INFORMATION_EX, IoCallDriver returns
with a STATUS_INVALID_ADDRESS error.

The code that the driver is calling is below.

For what is is worth, the driver is able to successfully send
IOCTL_TCP_SET_INFORMATION_EX for AO_OPTION_MCASTIF and AO_OPTION_MCASTTTL
using the same code.

Any ideas will be greatly appreciated.

TIA.
Code:

NTSTATUS
AddMulticast(
PFILE_OBJECT pFileObject,
ULONG IPAdd) // In host order
{
NSTATUS status
DEVICE_OBJECT pDeviceObject
IO__STATUS_BLOCK IoStatusBlock;
PIRP pIrp;
KEVENT event;
PTCP_REQUEST_SET_INFORMATION_EX pInputInfo;

ULONG remoteAddr = htonl(0xE000001);
ULONG localAddr = htonl(0xC0A8010F);
struct ip_mreq mreq;

mreq.imr_multiaddr.s_addr = remoteAddr;
mreq.imr_interface.s_addr = localAddr;

KeInitializeEvent(&event, NotificationEvent, FALSE);

pInputInfo = (PTCP_REQUEST_SET_INFORMATION_EX)ExAllocatePoolWithTag(
PagedPool,
sizeof(TCP_REQUEST_SET_INFORMATION_EX)+sizeof(struct ip_mreq),
JS_UTIL_TAG);

if (pInputInfo == NULL)
{
DBGPRINT(5, (“AddMulticast: Failed to allocate memory.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}

// Join the MCast group
RtlZeroMemory(pInputInfo,
sizeof(TCP_REQUEST_SET_INFORMATION_EX)+sizeof(struct ip_mreq));

pInputInfo->ID.toi_entity.tei_entity = CL_TL_ENTITY;
pInputInfo->ID.toi_entity.tei_instance = TL_INSTANCE;
pInputInfo->ID.toi_class = INFO_CLASS_PROTOCOL;
pInputInfo->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
pInputInfo->ID.toi_id = AO_OPTION_ADD_MCAST;
pInputInfo->BufferSize = sizeof(struct ip_mreq);
RtlCopyMemory(pInputInfo->Buffer, (PUCHAR)&mreq, sizeof(struct ip_mreq));
pDeviceObject = IoGetRelatedDeviceObject(pFileObject);

pIrp = IoBuildDeviceIoControlRequest( IOCTL_TCP_SET_INFORMATION_EX,
pDeviceObject,
pInputInfo,
sizeof(TCP_REQUEST_SET_INFORMATION_EX)+pInputInfo->BufferSize,
NULL,
0,
FALSE,
&event,
&IoStatusBlock);

PIO_STACK_LOCATION pStack;
pStack = IoGetNextIrpStackLocation(pIrp);
pStack->FileObject = pFileObject;

status = IoCallDriver(pDeviceObject, pIrp);
if(status == STATUS_PENDING)
{

KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock.Status;
}
else if (!NT_SUCCESS(status))
{
DBGPRINT(5, (“AddMulticast: Failed to add to multicast group. Status:
%#x.\n”, status));
}

ExFreePoolWithTag(pInput, JS_UTIL_TAG);

return status;
}

“JimmyJ” wrote in message news:xxxxx@ntdev…
> All,
>
> I am writing a TDI client driver to run on WinXP, SP2. One of the
> requirements of the driver is to send/rcv multicast packets. The driver
> works in conjunction with a WSK app that adds a local interface to the
> multicast cast group. Within the TDI client driver we are doing the
> following:
> 1. Binding to the IPMULTICAST device using the IP address of the local
> interface plus an arbitary port number.
> 2. To send the datagram, we are using TdiBuildSendDatagram with the
> SendDatagramInfo set with the address of the multicast add/port.
>
> When the driver calls IoCallDriver to send the datagram, it returns with
> and invalid parameter error.
>
> So the question is: can someone please tell me how to send a UDP datagram
> to a multicast group from within a TDI client driver?
>
> TIA,
> Jim
>
>
>
>

Oh wait I see that the problem is a type-o in the group address – I forgot
a zero. The address should be 0xe0000001 not 0xe000001.

At any rate the MCast join now works. I might be back if I can’t get the
local machine to actually receive.
Thanks,
Jim
“JimmyJ” wrote in message news:xxxxx@ntdev…
> Thanks for the replies.
>
> I fixed the UDP send problem so we’re good there but now I am trying to
> receive data from a multicast group.
>
> To receive, the driver is doing the following:
>
> - Bind to the UDP stack
> - Using the Local IP Add and the Multicast group address, the driver
> attempts to join the MCast group.
>
> When the driver send the IOCTL_TCP_SET_INFORMATION_EX, IoCallDriver
> returns with a STATUS_INVALID_ADDRESS error.
>
> The code that the driver is calling is below.
>
> For what is is worth, the driver is able to successfully send
> IOCTL_TCP_SET_INFORMATION_EX for AO_OPTION_MCASTIF and AO_OPTION_MCASTTTL
> using the same code.
>
> Any ideas will be greatly appreciated.
>
> TIA.
> Code:
>
> NTSTATUS
> AddMulticast(
> PFILE_OBJECT pFileObject,
> ULONG IPAdd) // In host order
> {
> NSTATUS status
> DEVICE_OBJECT pDeviceObject
> IO__STATUS_BLOCK IoStatusBlock;
> PIRP pIrp;
> KEVENT event;
> PTCP_REQUEST_SET_INFORMATION_EX pInputInfo;
>
> ULONG remoteAddr = htonl(0xE000001);
> ULONG localAddr = htonl(0xC0A8010F);
> struct ip_mreq mreq;
>
> mreq.imr_multiaddr.s_addr = remoteAddr;
> mreq.imr_interface.s_addr = localAddr;
>
> KeInitializeEvent(&event, NotificationEvent, FALSE);
>
> pInputInfo = (PTCP_REQUEST_SET_INFORMATION_EX)ExAllocatePoolWithTag(
> PagedPool,
> sizeof(TCP_REQUEST_SET_INFORMATION_EX)+sizeof(struct ip_mreq),
> JS_UTIL_TAG);
>
> if (pInputInfo == NULL)
> {
> DBGPRINT(5, (“AddMulticast: Failed to allocate memory.\n”));
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> // Join the MCast group
> RtlZeroMemory(pInputInfo,
> sizeof(TCP_REQUEST_SET_INFORMATION_EX)+sizeof(struct ip_mreq));
>
> pInputInfo->ID.toi_entity.tei_entity = CL_TL_ENTITY;
> pInputInfo->ID.toi_entity.tei_instance = TL_INSTANCE;
> pInputInfo->ID.toi_class = INFO_CLASS_PROTOCOL;
> pInputInfo->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
> pInputInfo->ID.toi_id = AO_OPTION_ADD_MCAST;
> pInputInfo->BufferSize = sizeof(struct ip_mreq);
> RtlCopyMemory(pInputInfo->Buffer, (PUCHAR)&mreq, sizeof(struct ip_mreq));
> pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
>
> pIrp = IoBuildDeviceIoControlRequest( IOCTL_TCP_SET_INFORMATION_EX,
> pDeviceObject,
> pInputInfo,
> sizeof(TCP_REQUEST_SET_INFORMATION_EX)+pInputInfo->BufferSize,
> NULL,
> 0,
> FALSE,
> &event,
> &IoStatusBlock);
>
> PIO_STACK_LOCATION pStack;
> pStack = IoGetNextIrpStackLocation(pIrp);
> pStack->FileObject = pFileObject;
>
> status = IoCallDriver(pDeviceObject, pIrp);
> if(status == STATUS_PENDING)
> {
>
> KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
> status = IoStatusBlock.Status;
> }
> else if (!NT_SUCCESS(status))
> {
> DBGPRINT(5, (“AddMulticast: Failed to add to multicast group. Status:
> %#x.\n”, status));
> }
>
> ExFreePoolWithTag(pInput, JS_UTIL_TAG);
>
> return status;
> }
>
>
>
> “JimmyJ” wrote in message news:xxxxx@ntdev…
>> All,
>>
>> I am writing a TDI client driver to run on WinXP, SP2. One of the
>> requirements of the driver is to send/rcv multicast packets. The driver
>> works in conjunction with a WSK app that adds a local interface to the
>> multicast cast group. Within the TDI client driver we are doing the
>> following:
>> 1. Binding to the IPMULTICAST device using the IP address of the local
>> interface plus an arbitary port number.
>> 2. To send the datagram, we are using TdiBuildSendDatagram with the
>> SendDatagramInfo set with the address of the multicast add/port.
>>
>> When the driver calls IoCallDriver to send the datagram, it returns with
>> and invalid parameter error.
>>
>> So the question is: can someone please tell me how to send a UDP datagram
>> to a multicast group from within a TDI client driver?
>>
>> TIA,
>> Jim
>>
>>
>>
>>
>
>
>