Error while calling to wsksendto (STATUS_DATA_NOT_ACCEPTED)

I am getting status_data_not_accepted (0xc000021b) error while calling to wsksendto

This is a simple udp client using WSK api which simply needs to send packet (no need to receive). Initially I was not calling wskbind but after reading through MSDN I realized that I need to invoke wskbind. When I was not doing WSKBind I was getting a different error signifying the device is not initialized. After I am doing wskbind, I am getting an error below:

7: kd> !error -0n1073741285
Error code: (NTSTATUS) 0xc000021b (3221226011) - {Data Not Accepted} The TDI client could not handle the data received during an indication.

Can someone please help me here? I am pasting my code below for reference.

=====
WSK_REGISTRATION gCliReg;
WSK_PROVIDER_NPI gProNPI;
WSK_CLIENT_NPI gCliNPI;

NTSTATUS
InitWSK()
{
NTSTATUS status;
WSK_CLIENT_DISPATCH dispatch = { MAKE_WSK_VERSION(1, 0), 0, NULL };
gCliNPI.ClientContext = NULL;
gCliNPI.Dispatch = &dispatch;
status = WskRegister(&gCliNPI, &gCliReg);
if(!NT_SUCCESS(status)){
DbgPrint(“WskRegister() error : 0x%X\n”, status);
return status;
}
status = WskCaptureProviderNPI(&gCliReg, WSK_INFINITE_WAIT, &gProNPI);
if(!NT_SUCCESS(status)){
DbgPrint(“WskCaptureProviderNPI() error : 0x%X\n”, status);
WskDeregister(&gCliReg);
return status;
}
return STATUS_SUCCESS;
}

NTSTATUS
CreateSocketComplete(
PDEVICE_OBJECT DevObj,
PIRP Irp,
PVOID Context
)
{
UNREFERENCED_PARAMETER(DevObj);
UNREFERENCED_PARAMETER(Irp);
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
CreateSocket(
PWSK_SOCKET *Sock
)
{
NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp;
KEVENT event;
PWSK_PROVIDER_NPI ProNPI = &gProNPI;

Irp = IoAllocateIrp(1, FALSE);
if(!Irp){
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(Irp, CreateSocketComplete, &event, TRUE, TRUE, TRUE);
ProNPI->Dispatch->WskSocket(
ProNPI->Client,
AF_INET,
SOCK_DGRAM,
IPPROTO_UDP,
WSK_FLAG_DATAGRAM_SOCKET,
NULL,
NULL,
NULL, // Impersonate process
NULL, // Impersonate thread
NULL, // Security descriptor
Irp
);
WAIT_ON_COMPLETION_LOG_ON_ERROR(CreateSocket,Status,event,Irp);
(*Sock) = (PWSK_SOCKET)Irp->IoStatus.Information;
return Status;
}

NTSTATUS
SetCompletionEvent
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PKEVENT compEvent = (PKEVENT)Context;

UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
KeSetEvent(compEvent, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
InitializeSock(
PWSK_SOCKET *Sock,
USHORT PortId
)
{
NTSTATUS Status;
PIRP Irp;
KEVENT event;
PFN_WSK_CONTROL_SOCKET WskControlSocket;
SOCKADDR_IN addr;

Irp = IoAllocateIrp(1, FALSE);
if(!Irp){
return STATUS_INSUFFICIENT_RESOURCES;
}
WskControlSocket = ((CONST PWSK_PROVIDER_BASIC_DISPATCH)(*Sock)->Dispatch)->WskControlSocket;
KeInitializeEvent(&event, NotificationEvent, FALSE);

IoSetCompletionRoutine(Irp,SetCompletionEvent,&event,TRUE,TRUE,TRUE);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = RtlUlongByteSwap(INADDR_ANY);
addr.sin_port = RtlUshortByteSwap((short)PortId);
Status = ((CONST WSK_PROVIDER_DATAGRAM_DISPATCH *)(*Sock)->Dispatch)->WskBind(
(*Sock),
(PSOCKADDR)&addr,
0,
Irp
);
WAIT_ON_COMPLETION_LOG_ON_ERROR(WskBind, Status, event, Irp);
return Status;
}

VOID
CleanupWSK()
{
WskReleaseProviderNPI(&gCliReg);
WskDeregister(&gCliReg);
return;
}

NTSTATUS
SendTo(PWSK_SOCKET sock, PSOCKADDR RemoteAddress, PVOID data, ULONG datal)
{
WSK_BUF wskbuf;
NTSTATUS status;
KEVENT event;
PIRP irp;
irp = IoAllocateIrp(1, FALSE);
if(!irp){
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(irp, SendDataComplete, &event, TRUE, TRUE, TRUE);
wskbuf.Mdl = IoAllocateMdl(data, datal, FALSE, FALSE, NULL);
if(!wskbuf.Mdl){
DbgPrint(“Failed to allocate MDL!\n”);
return STATUS_MORE_PROCESSING_REQUIRED;
}
MmBuildMdlForNonPagedPool(wskbuf.Mdl);
wskbuf.Offset = 0;
wskbuf.Length = datal;
DbgBreakPoint();
status = ((PWSK_PROVIDER_DATAGRAM_DISPATCH)(sock->Dispatch))->WskSendTo(sock, &wskbuf, 0, RemoteAddress, 0, NULL, irp);
WAIT_ON_COMPLETION_LOG_ON_ERROR(WskSendTo, status, event, irp);
return status;
}

NTSTATUS
SendDataComplete(PDEVICE_OBJECT devobj, PIRP irp, PVOID context)
{
UNREFERENCED_PARAMETER(devobj);
UNREFERENCED_PARAMETER(irp);
KeSetEvent((PKEVENT)context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

VOID
TestUdpSocket()
{
PWSK_SOCKET Sock = NULL;
NTSTATUS status = STATUS_SUCCESS;
SOCKADDR_IN RemoteAddress;
char Data[100] = “TEST”;
int DataLength = 4;
status = CreateSocket(&Sock);
if(status != STATUS_SUCCESS)
{
DbgPrint(“Error: %d in creating socket \n”,status);
return;
}
InitializeSock(&Sock, 0);
RemoteAddress.sin_family = AF_INET;
RemoteAddress.sin_addr.s_addr = RtlUlongByteSwap((ULONG)GLOBBAL_SERVER_ADDR);
RemoteAddress.sin_port = RtlUshortByteSwap((short)GLOBAL_PORT);

SendTo(Sock,(PSOCKADDR)&RemoteAddress, Data, DataLength);
}

While the code might be interesting, an error such as “data not accepted”
quite likely depends on the specific values used in the call. For
example, what is the data length? Note that UDP has an upper bound on the
length of a packet; any value larger than that upper bound (which, if I
remember correctlvy, is 536 bytes, allowing for 24 bytes of header and 512
bytes of data) may be whinsically truncated to that upper bound anywhere
along the path. There is no guarantee. That said, I have no experience
in calling network interfaces within the kernel, but my first thought
would be to examine all the parameters at the site of the call. Showing
code does not show values, and it would be important to see ALL the
values, both as they come into your function and how they are presented to
the call (including values in all structures). It might be that the
internal interfaces are fussier about data lengths than the user API.

Inaddition, “bind” is an operation which “publishes” a port ID so that
connections can be made TO it. If you are sending, the recipient at the
IP address you give must bind the port ID you are sending to, or the
packet will be rejected. If the “bind” function you are calling does
that, it is inappropriate; I suspect that the act of binding results in a
necessary initialization you should be doing differently, but have not
done. At least at the user API level the “bind” would be incorrect.

I am curious why you block the thread until the completion routine
unblocks it. This appears, superficially, to be a manifestation of the
syntax-means-sequentiality model which is inappropriate for asynchronous
architectures. That is, you want to write A(); B(); because B follows A.
So obviously that is the way to code it, and because of the asynchrony you
feel you need to write it as A(); wait_for_A_completion(); B(); where your
A_completion body is simply signal_A_complete(); which releases the wait.
But why do you do that when you could simply write A(); and have
A_completion consist of doing B();? I see this error a lot in application
code, as the programmer desperately tries to maintain the
sequential-syntax-implies-sequential-execution model (or perhaps the
sequential-execution-requires-sequential-syntax model), and therefore I
tend to question the validity of this model every time I see it. The
major issue is that this blocks the sending thread, which can have
significant consequences to overall app and/or system behavior, and
typically is unnecessary. There is a major paradigm shift to the
asynchronous execution model, and attempts to maintain the synchronous
execution model are often the cause of significant second-order problems;
I once saw a $500,000 project collapse because of an early decision to
maintain a synchronous model in what was an asynchronous universe. When
the second-order problems resulted in total failure, only a total rewrite
of the app could have saved it. And there was no budget for that.
joe

I am getting status_data_not_accepted (0xc000021b) error while calling to
wsksendto

This is a simple udp client using WSK api which simply needs to send
packet (no need to receive). Initially I was not calling wskbind but after
reading through MSDN I realized that I need to invoke wskbind. When I was
not doing WSKBind I was getting a different error signifying the device is
not initialized. After I am doing wskbind, I am getting an error below:

7: kd> !error -0n1073741285
Error code: (NTSTATUS) 0xc000021b (3221226011) - {Data Not Accepted} The
TDI client could not handle the data received during an indication.

Can someone please help me here? I am pasting my code below for reference.

=====
WSK_REGISTRATION gCliReg;
WSK_PROVIDER_NPI gProNPI;
WSK_CLIENT_NPI gCliNPI;

NTSTATUS
InitWSK()
{
NTSTATUS status;
WSK_CLIENT_DISPATCH dispatch = { MAKE_WSK_VERSION(1, 0), 0, NULL };
gCliNPI.ClientContext = NULL;
gCliNPI.Dispatch = &dispatch;
status = WskRegister(&gCliNPI, &gCliReg);
if(!NT_SUCCESS(status)){
DbgPrint(“WskRegister() error : 0x%X\n”, status);
return status;
}
status = WskCaptureProviderNPI(&gCliReg, WSK_INFINITE_WAIT, &gProNPI);
if(!NT_SUCCESS(status)){
DbgPrint(“WskCaptureProviderNPI() error : 0x%X\n”, status);
WskDeregister(&gCliReg);
return status;
}
return STATUS_SUCCESS;
}

NTSTATUS
CreateSocketComplete(
PDEVICE_OBJECT DevObj,
PIRP Irp,
PVOID Context
)
{
UNREFERENCED_PARAMETER(DevObj);
UNREFERENCED_PARAMETER(Irp);
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
CreateSocket(
PWSK_SOCKET *Sock
)
{
NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp;
KEVENT event;
PWSK_PROVIDER_NPI ProNPI = &gProNPI;

Irp = IoAllocateIrp(1, FALSE);
if(!Irp){
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(Irp, CreateSocketComplete, &event, TRUE, TRUE,
TRUE);
ProNPI->Dispatch->WskSocket(
ProNPI->Client,
AF_INET,
SOCK_DGRAM,
IPPROTO_UDP,
WSK_FLAG_DATAGRAM_SOCKET,
NULL,
NULL,
NULL, // Impersonate process
NULL, // Impersonate thread
NULL, // Security descriptor
Irp
);
WAIT_ON_COMPLETION_LOG_ON_ERROR(CreateSocket,Status,event,Irp);
(*Sock) = (PWSK_SOCKET)Irp->IoStatus.Information;
return Status;
}

NTSTATUS
SetCompletionEvent
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PKEVENT compEvent = (PKEVENT)Context;

UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
KeSetEvent(compEvent, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
InitializeSock(
PWSK_SOCKET *Sock,
USHORT PortId
)
{
NTSTATUS Status;
PIRP Irp;
KEVENT event;
PFN_WSK_CONTROL_SOCKET WskControlSocket;
SOCKADDR_IN addr;

Irp = IoAllocateIrp(1, FALSE);
if(!Irp){
return STATUS_INSUFFICIENT_RESOURCES;
}
WskControlSocket = ((CONST
PWSK_PROVIDER_BASIC_DISPATCH)(*Sock)->Dispatch)->WskControlSocket;
KeInitializeEvent(&event, NotificationEvent, FALSE);

IoSetCompletionRoutine(Irp,SetCompletionEvent,&event,TRUE,TRUE,TRUE);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = RtlUlongByteSwap(INADDR_ANY);
addr.sin_port = RtlUshortByteSwap((short)PortId);
Status = ((CONST WSK_PROVIDER_DATAGRAM_DISPATCH
*)(*Sock)->Dispatch)->WskBind(
(*Sock),
(PSOCKADDR)&addr,
0,
Irp
);
WAIT_ON_COMPLETION_LOG_ON_ERROR(WskBind, Status, event, Irp);
return Status;
}

VOID
CleanupWSK()
{
WskReleaseProviderNPI(&gCliReg);
WskDeregister(&gCliReg);
return;
}

NTSTATUS
SendTo(PWSK_SOCKET sock, PSOCKADDR RemoteAddress, PVOID data, ULONG datal)
{
WSK_BUF wskbuf;
NTSTATUS status;
KEVENT event;
PIRP irp;
irp = IoAllocateIrp(1, FALSE);
if(!irp){
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(irp, SendDataComplete, &event, TRUE, TRUE,
TRUE);
wskbuf.Mdl = IoAllocateMdl(data, datal, FALSE, FALSE, NULL);
if(!wskbuf.Mdl){
DbgPrint(“Failed to allocate MDL!\n”);
return STATUS_MORE_PROCESSING_REQUIRED;
}
MmBuildMdlForNonPagedPool(wskbuf.Mdl);
wskbuf.Offset = 0;
wskbuf.Length = datal;
DbgBreakPoint();
status =
((PWSK_PROVIDER_DATAGRAM_DISPATCH)(sock->Dispatch))->WskSendTo(sock,
&wskbuf, 0, RemoteAddress, 0, NULL, irp);
WAIT_ON_COMPLETION_LOG_ON_ERROR(WskSendTo, status, event, irp);
return status;
}

NTSTATUS
SendDataComplete(PDEVICE_OBJECT devobj, PIRP irp, PVOID context)
{
UNREFERENCED_PARAMETER(devobj);
UNREFERENCED_PARAMETER(irp);
KeSetEvent((PKEVENT)context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

VOID
TestUdpSocket()
{
PWSK_SOCKET Sock = NULL;
NTSTATUS status = STATUS_SUCCESS;
SOCKADDR_IN RemoteAddress;
char Data[100] = “TEST”;
int DataLength = 4;
status = CreateSocket(&Sock);
if(status != STATUS_SUCCESS)
{
DbgPrint(“Error: %d in creating socket \n”,status);
return;
}
InitializeSock(&Sock, 0);
RemoteAddress.sin_family = AF_INET;
RemoteAddress.sin_addr.s_addr =
RtlUlongByteSwap((ULONG)GLOBBAL_SERVER_ADDR);
RemoteAddress.sin_port = RtlUshortByteSwap((short)GLOBAL_PORT);

SendTo(Sock,(PSOCKADDR)&RemoteAddress, Data, DataLength);
}


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

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