1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=4:tabstop=4:
4 * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define DEBUG_SUBSYSTEM S_LIBCFS
24 #include <libcfs/libcfs.h>
25 #include <lnet/lnet.h>
27 #define TDILND_MODULE_NAME L"Tdilnd"
32 ks_tdi_send_flags(ULONG SockFlags)
36 if (cfs_is_flag_set(SockFlags, MSG_OOB)) {
37 cfs_set_flag(TdiFlags, TDI_SEND_EXPEDITED);
40 if (cfs_is_flag_set(SockFlags, MSG_MORE)) {
41 cfs_set_flag(TdiFlags, TDI_SEND_PARTIAL);
44 if (cfs_is_flag_set(SockFlags, MSG_DONTWAIT)) {
45 cfs_set_flag(TdiFlags, TDI_SEND_NON_BLOCKING);
52 KsIrpCompletionRoutine(
53 IN PDEVICE_OBJECT DeviceObject,
58 if (NULL != Context) {
59 KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
62 return STATUS_MORE_PROCESSING_REQUIRED;
64 UNREFERENCED_PARAMETER(DeviceObject);
65 UNREFERENCED_PARAMETER(Irp);
71 * Allocate a new IRP and initialize it to be issued to tdi
74 * DeviceObject: device object created by the underlying
75 * TDI transport driver
78 * PRIP: the allocated Irp in success or NULL in failure.
86 IN PDEVICE_OBJECT DeviceObject
90 PIO_STACK_LOCATION IrpSp;
93 // Allocating the IRP ...
96 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
101 // Getting the Next Stack Location ...
104 IrpSp = IoGetNextIrpStackLocation(Irp);
107 // Initializing Irp ...
110 IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
111 IrpSp->Parameters.DeviceIoControl.IoControlCode = 0;
119 * Issue the Irp to the underlying tdi driver
122 * DeviceObject: the device object created by TDI driver
123 * Irp: the I/O request packet to be processed
124 * bSynchronous: synchronous or not. If true, we need wait
125 * until the process is finished.
126 * Information: returned info
129 * NTSTATUS: kernel status code
137 IN PDEVICE_OBJECT DeviceObject,
139 IN BOOLEAN bSynchronous,
140 OUT PULONG Information
150 SynchronizationEvent,
155 IoSetCompletionRoutine(
157 KsIrpCompletionRoutine,
165 Status = IoCallDriver(DeviceObject, Irp);
169 if (STATUS_PENDING == Status) {
171 Status = KeWaitForSingleObject(
180 Status = Irp->IoStatus.Status;
183 *Information = (ULONG)(Irp->IoStatus.Information);
186 Irp->MdlAddress = NULL;
190 if (!NT_SUCCESS(Status)) {
192 KsPrint((2, "KsSubmitTdiIrp: Error when submitting the Irp: Status = %xh (%s) ...\n",
193 Status, KsNtStatusToString(Status)));
203 * Open the Control Channel Object ...
206 * DeviceName: the device name to be opened
207 * Handle: opened handle in success case
208 * FileObject: the fileobject of the device
211 * NTSTATUS: kernel status code (STATUS_SUCCESS
212 * or other error code)
220 IN PUNICODE_STRING DeviceName,
222 OUT PFILE_OBJECT * FileObject
225 NTSTATUS Status = STATUS_SUCCESS;
227 OBJECT_ATTRIBUTES ObjectAttributes;
228 IO_STATUS_BLOCK IoStatus;
231 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
237 InitializeObjectAttributes(
240 OBJ_CASE_INSENSITIVE |
246 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
249 // Creating the Transport Address Object ...
252 Status = ZwCreateFile(
254 FILE_READ_DATA | FILE_WRITE_DATA,
258 FILE_ATTRIBUTE_NORMAL,
259 FILE_SHARE_READ | FILE_SHARE_WRITE,
267 if (NT_SUCCESS(Status)) {
270 // Now Obtaining the FileObject of the Transport Address ...
273 Status = ObReferenceObjectByHandle(
282 if (!NT_SUCCESS(Status)) {
284 cfs_enter_debugger();
290 cfs_enter_debugger();
299 * Release the Control Channel Handle and FileObject
302 * Handle: the channel handle to be released
303 * FileObject: the fileobject to be released
306 * NTSTATUS: kernel status code (STATUS_SUCCESS
307 * or other error code)
316 IN PFILE_OBJECT FileObject
319 NTSTATUS Status = STATUS_SUCCESS;
321 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
325 ObDereferenceObject(FileObject);
330 Status = ZwClose(Handle);
333 ASSERT(NT_SUCCESS(Status));
341 * Open the tdi address object
344 * DeviceName: device name of the address object
345 * pAddress: tdi address of the address object
346 * AddressLength: length in bytes of the tdi address
347 * Handle: the newly opened handle
348 * FileObject: the newly opened fileobject
351 * NTSTATUS: kernel status code (STATUS_SUCCESS
352 * or other error code)
360 IN PUNICODE_STRING DeviceName,
361 IN PTRANSPORT_ADDRESS pAddress,
362 IN ULONG AddressLength,
364 OUT PFILE_OBJECT * FileObject
367 NTSTATUS Status = STATUS_SUCCESS;
369 PFILE_FULL_EA_INFORMATION Ea = NULL;
371 UCHAR EaBuffer[EA_MAX_LENGTH];
373 OBJECT_ATTRIBUTES ObjectAttributes;
374 IO_STATUS_BLOCK IoStatus;
377 // Building EA for the Address Object to be Opened ...
380 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
381 Ea->NextEntryOffset = 0;
383 Ea->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
384 Ea->EaValueLength = (USHORT)AddressLength;
391 &(Ea->EaName[Ea->EaNameLength + 1]),
395 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
396 Ea->EaNameLength + AddressLength;
398 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
405 InitializeObjectAttributes(
408 OBJ_CASE_INSENSITIVE |
414 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
417 // Creating the Transport Address Object ...
420 Status = ZwCreateFile(
422 FILE_READ_DATA | FILE_WRITE_DATA,
426 FILE_ATTRIBUTE_NORMAL,
427 FILE_SHARE_READ | FILE_SHARE_WRITE, /* 0: DON'T REUSE */
435 if (NT_SUCCESS(Status)) {
438 // Now Obtaining the FileObject of the Transport Address ...
441 Status = ObReferenceObjectByHandle(
450 if (!NT_SUCCESS(Status)) {
452 cfs_enter_debugger();
458 cfs_enter_debugger();
466 * Release the Hanlde and FileObject of an opened tdi
470 * Handle: the handle to be released
471 * FileObject: the fileobject to be released
474 * NTSTATUS: kernel status code (STATUS_SUCCESS
475 * or other error code)
484 IN PFILE_OBJECT FileObject
487 NTSTATUS Status = STATUS_SUCCESS;
491 ObDereferenceObject(FileObject);
496 Status = ZwClose(Handle);
499 ASSERT(NT_SUCCESS(Status));
507 * Open a tdi connection object
510 * DeviceName: device name of the connection object
511 * ConnectionContext: the connection context
512 * Handle: the newly opened handle
513 * FileObject: the newly opened fileobject
516 * NTSTATUS: kernel status code (STATUS_SUCCESS
517 * or other error code)
525 IN PUNICODE_STRING DeviceName,
526 IN CONNECTION_CONTEXT ConnectionContext,
528 OUT PFILE_OBJECT * FileObject
531 NTSTATUS Status = STATUS_SUCCESS;
533 PFILE_FULL_EA_INFORMATION Ea = NULL;
535 UCHAR EaBuffer[EA_MAX_LENGTH];
537 OBJECT_ATTRIBUTES ObjectAttributes;
538 IO_STATUS_BLOCK IoStatus;
541 // Building EA for the Address Object to be Opened ...
544 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
545 Ea->NextEntryOffset = 0;
547 Ea->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
548 Ea->EaValueLength = (USHORT)sizeof(CONNECTION_CONTEXT);
551 TdiConnectionContext,
555 &(Ea->EaName[Ea->EaNameLength + 1]),
557 sizeof(CONNECTION_CONTEXT)
559 EaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
560 Ea->EaNameLength + 1 + sizeof(CONNECTION_CONTEXT);
562 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
569 InitializeObjectAttributes(
572 OBJ_CASE_INSENSITIVE |
578 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
581 // Creating the Connection Object ...
584 Status = ZwCreateFile(
586 FILE_READ_DATA | FILE_WRITE_DATA,
590 FILE_ATTRIBUTE_NORMAL,
599 if (NT_SUCCESS(Status)) {
602 // Now Obtaining the FileObject of the Transport Address ...
605 Status = ObReferenceObjectByHandle(
614 if (!NT_SUCCESS(Status)) {
616 cfs_enter_debugger();
622 cfs_enter_debugger();
630 * Release the Hanlde and FileObject of an opened tdi
634 * Handle: the handle to be released
635 * FileObject: the fileobject to be released
638 * NTSTATUS: kernel status code (STATUS_SUCCESS
639 * or other error code)
648 IN PFILE_OBJECT FileObject
651 NTSTATUS Status = STATUS_SUCCESS;
655 ObDereferenceObject(FileObject);
660 Status = ZwClose(Handle);
663 ASSERT(NT_SUCCESS(Status));
671 * Associate an address object with a connection object
674 * AddressHandle: the handle of the address object
675 * ConnectionObject: the FileObject of the connection
678 * NTSTATUS: kernel status code (STATUS_SUCCESS
679 * or other error code)
687 IN HANDLE AddressHandle,
688 IN PFILE_OBJECT ConnectionObject
692 PDEVICE_OBJECT DeviceObject;
696 // Getting the DeviceObject from Connection FileObject
699 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
702 // Building Tdi Internal Irp ...
705 Irp = KsBuildTdiIrp(DeviceObject);
709 Status = STATUS_INSUFFICIENT_RESOURCES;
714 // Assocating the Address Object with the Connection Object
717 TdiBuildAssociateAddress(
727 // Calling the Transprot Driver with the Prepared Irp
730 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
738 * KsDisassociateAddress
739 * Disassociate the connection object (the relationship will
740 * the corresponding address object will be dismissed. )
743 * ConnectionObject: the FileObject of the connection
746 * NTSTATUS: kernel status code (STATUS_SUCCESS
747 * or other error code)
754 KsDisassociateAddress(
755 IN PFILE_OBJECT ConnectionObject
759 PDEVICE_OBJECT DeviceObject;
763 // Getting the DeviceObject from Connection FileObject
766 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
769 // Building Tdi Internal Irp ...
772 Irp = KsBuildTdiIrp(DeviceObject);
776 Status = STATUS_INSUFFICIENT_RESOURCES;
781 // Disassocating the Address Object with the Connection Object
784 TdiBuildDisassociateAddress(
793 // Calling the Transprot Driver with the Prepared Irp
796 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
806 // Connection Control Event Callbacks
814 // Tcp Event Callbacks
818 TDI_EVENT_RECEIVE_EXPEDITED
819 TDI_EVENT_CHAINED_RECEIVE
820 TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
823 // Udp Event Callbacks
826 TDI_EVENT_RECEIVE_DATAGRAM
827 TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
834 * Set the tdi event callbacks with an address object
837 * AddressObject: the FileObject of the address object
838 * EventContext: the parameter for the callbacks
839 * Handlers: the handlers indictor array
842 * NTSTATUS: kernel status code (STATUS_SUCCESS
843 * or other error code)
851 IN PFILE_OBJECT AddressObject, // Address File Object
852 IN PVOID EventContext, // Context for Handlers
853 IN PKS_EVENT_HANDLERS Handlers // Handlers Indictor
856 NTSTATUS Status = STATUS_SUCCESS;
857 PDEVICE_OBJECT DeviceObject;
860 DeviceObject = IoGetRelatedDeviceObject(AddressObject);
862 for (i=0; i < TDI_EVENT_MAXIMUM_HANDLER; i++) {
865 // Setup the tdi event callback handler if requested.
868 if (Handlers->IsActive[i]) {
873 // Building Tdi Internal Irp ...
876 Irp = KsBuildTdiIrp(DeviceObject);
880 Status = STATUS_INSUFFICIENT_RESOURCES;
885 // Building the Irp to set the Event Handler ...
888 TdiBuildSetEventHandler(
894 i, /* tdi event type */
895 Handlers->Handler[i], /* tdi event handler */
896 EventContext /* context for the handler */
900 // Calling the Transprot Driver with the Prepared Irp
903 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
906 // tcp/ip tdi does not support these two event callbacks
909 if ((!NT_SUCCESS(Status)) && ( i == TDI_EVENT_SEND_POSSIBLE ||
910 i == TDI_EVENT_CHAINED_RECEIVE_EXPEDITED )) {
911 cfs_enter_debugger();
912 Status = STATUS_SUCCESS;
916 if (!NT_SUCCESS(Status)) {
917 cfs_enter_debugger();
926 if (!NT_SUCCESS(Status)) {
928 KsPrint((2, "KsSetEventHandlers: Error Status = %xh (%s)\n",
929 Status, KsNtStatusToString(Status) ));
939 * Query the address of the FileObject specified
942 * FileObject: the FileObject to be queried
943 * AddressInfo: buffer to contain the address info
944 * AddressSize: length of the AddressInfo buffer
947 * NTSTATUS: kernel status code (STATUS_SUCCESS
948 * or other error code)
956 PFILE_OBJECT FileObject,
957 PTDI_ADDRESS_INFO AddressInfo,
961 NTSTATUS Status = STATUS_UNSUCCESSFUL;
964 PDEVICE_OBJECT DeviceObject;
966 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
968 DeviceObject = IoGetRelatedDeviceObject(FileObject);
970 RtlZeroMemory(AddressInfo, *(AddressSize));
973 // Allocating the Tdi Setting Irp ...
976 Irp = KsBuildTdiIrp(DeviceObject);
980 Status = STATUS_INSUFFICIENT_RESOURCES;
985 // Locking the User Buffer / Allocating a MDL for it
988 Status = KsLockUserBuffer(
996 if (!NT_SUCCESS(Status)) {
1005 LASSERT(NT_SUCCESS(Status));
1007 TdiBuildQueryInformation(
1013 TDI_QUERY_ADDRESS_INFO,
1017 Status = KsSubmitTdiIrp(
1024 KsReleaseMdl(Mdl, FALSE);
1027 if (!NT_SUCCESS(Status)) {
1029 cfs_enter_debugger();
1030 //TDI_BUFFER_OVERFLOW
1037 * KsQueryProviderInfo
1038 * Query the underlying transport device's information
1041 * TdiDeviceName: the transport device's name string
1042 * ProviderInfo: TDI_PROVIDER_INFO struncture
1045 * NTSTATUS: Nt system status code
1052 KsQueryProviderInfo(
1053 PWSTR TdiDeviceName,
1054 PTDI_PROVIDER_INFO ProviderInfo
1057 NTSTATUS Status = STATUS_SUCCESS;
1062 UNICODE_STRING ControlName;
1065 PFILE_OBJECT FileObject;
1066 PDEVICE_OBJECT DeviceObject;
1068 ULONG ProviderSize = 0;
1070 RtlInitUnicodeString(&ControlName, TdiDeviceName);
1073 // Open the Tdi Control Channel
1076 Status = KsOpenControl(
1082 if (!NT_SUCCESS(Status)) {
1084 KsPrint((2, "KsQueryProviderInfo: Fail to open the tdi control channel.\n"));
1089 // Obtain The Related Device Object
1092 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1094 ProviderSize = sizeof(TDI_PROVIDER_INFO);
1095 RtlZeroMemory(ProviderInfo, ProviderSize);
1098 // Allocating the Tdi Setting Irp ...
1101 Irp = KsBuildTdiIrp(DeviceObject);
1105 Status = STATUS_INSUFFICIENT_RESOURCES;
1110 // Locking the User Buffer / Allocating a MDL for it
1113 Status = KsLockUserBuffer(
1121 if (!NT_SUCCESS(Status)) {
1130 LASSERT(NT_SUCCESS(Status));
1132 TdiBuildQueryInformation(
1138 TDI_QUERY_PROVIDER_INFO,
1142 Status = KsSubmitTdiIrp(
1149 KsReleaseMdl(Mdl, FALSE);
1152 if (!NT_SUCCESS(Status)) {
1154 cfs_enter_debugger();
1155 //TDI_BUFFER_OVERFLOW
1158 KsCloseControl(Handle, FileObject);
1164 * KsQueryConnectionInfo
1165 * Query the connection info of the FileObject specified
1166 * (some statics data of the traffic)
1169 * FileObject: the FileObject to be queried
1170 * ConnectionInfo: buffer to contain the connection info
1171 * ConnectionSize: length of the ConnectionInfo buffer
1174 * NTSTATUS: kernel status code (STATUS_SUCCESS
1175 * or other error code)
1182 KsQueryConnectionInfo(
1183 PFILE_OBJECT ConnectionObject,
1184 PTDI_CONNECTION_INFO ConnectionInfo,
1185 PULONG ConnectionSize
1188 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1191 PDEVICE_OBJECT DeviceObject;
1193 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
1195 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
1197 RtlZeroMemory(ConnectionInfo, *(ConnectionSize));
1200 // Allocating the Tdi Query Irp ...
1203 Irp = KsBuildTdiIrp(DeviceObject);
1207 Status = STATUS_INSUFFICIENT_RESOURCES;
1212 // Locking the User Buffer / Allocating a MDL for it
1215 Status = KsLockUserBuffer(
1223 if (NT_SUCCESS(Status)) {
1232 LASSERT(NT_SUCCESS(Status));
1234 TdiBuildQueryInformation(
1240 TDI_QUERY_CONNECTION_INFO,
1244 Status = KsSubmitTdiIrp(
1251 KsReleaseMdl(Mdl, FALSE);
1259 * KsInitializeTdiAddress
1260 * Initialize the tdi addresss
1263 * pTransportAddress: tdi address to be initialized
1264 * IpAddress: the ip address of object
1265 * IpPort: the ip port of the object
1268 * ULONG: the total size of the tdi address
1275 KsInitializeTdiAddress(
1276 IN OUT PTA_IP_ADDRESS pTransportAddress,
1281 pTransportAddress->TAAddressCount = 1;
1282 pTransportAddress->Address[ 0 ].AddressLength = TDI_ADDRESS_LENGTH_IP;
1283 pTransportAddress->Address[ 0 ].AddressType = TDI_ADDRESS_TYPE_IP;
1284 pTransportAddress->Address[ 0 ].Address[ 0 ].sin_port = IpPort;
1285 pTransportAddress->Address[ 0 ].Address[ 0 ].in_addr = IpAddress;
1287 return (FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) + TDI_ADDRESS_LENGTH_IP);
1291 * KsQueryTdiAddressLength
1292 * Query the total size of the tdi address
1295 * pTransportAddress: tdi address to be queried
1298 * ULONG: the total size of the tdi address
1305 KsQueryTdiAddressLength(
1306 PTRANSPORT_ADDRESS pTransportAddress
1309 ULONG TotalLength = 0;
1312 PTA_ADDRESS UNALIGNED pTaAddress = NULL;
1314 ASSERT (NULL != pTransportAddress);
1316 TotalLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) +
1317 FIELD_OFFSET(TA_ADDRESS, Address) * pTransportAddress->TAAddressCount;
1319 pTaAddress = (TA_ADDRESS UNALIGNED *)pTransportAddress->Address;
1321 for (i = 0; i < pTransportAddress->TAAddressCount; i++)
1323 TotalLength += pTaAddress->AddressLength;
1324 pTaAddress = (TA_ADDRESS UNALIGNED *)((PCHAR)pTaAddress +
1325 FIELD_OFFSET(TA_ADDRESS,Address) +
1326 pTaAddress->AddressLength );
1329 return (TotalLength);
1335 * Query the ip address of the tdi object
1338 * FileObject: tdi object to be queried
1339 * TdiAddress: TdiAddress buffer, to store the queried
1341 * AddressLength: buffer length of the TdiAddress
1344 * ULONG: the total size of the tdi ip address
1352 PFILE_OBJECT FileObject,
1354 ULONG* AddressLength
1359 PTDI_ADDRESS_INFO TdiAddressInfo;
1364 // Maximum length of TDI_ADDRESSS_INFO with one TRANSPORT_ADDRESS
1367 Length = MAX_ADDRESS_LENGTH;
1369 TdiAddressInfo = (PTDI_ADDRESS_INFO)
1370 ExAllocatePoolWithTag(
1375 if (NULL == TdiAddressInfo) {
1377 Status = STATUS_INSUFFICIENT_RESOURCES;
1382 Status = KsQueryAddressInfo(
1390 if (NT_SUCCESS(Status))
1392 if (*AddressLength < Length) {
1394 Status = STATUS_BUFFER_TOO_SMALL;
1398 *AddressLength = Length;
1401 &(TdiAddressInfo->Address),
1405 Status = STATUS_SUCCESS;
1413 if (NULL != TdiAddressInfo) {
1415 ExFreePool(TdiAddressInfo);
1423 * KsErrorEventHandler
1424 * the common error event handler callback
1427 * TdiEventContext: should be the socket
1428 * Status: the error code
1431 * Status: STATS_SUCCESS
1434 * We need not do anything in such a severe
1435 * error case. System will process it for us.
1439 KsErrorEventHandler(
1440 IN PVOID TdiEventContext,
1444 KsPrint((2, "KsErrorEventHandler called at Irql = %xh ...\n",
1445 KeGetCurrentIrql()));
1447 cfs_enter_debugger();
1449 return (STATUS_SUCCESS);
1455 * setup all the event handler callbacks
1458 * tconn: the tdi connecton object
1461 * int: ks error code
1469 ksock_tconn_t * tconn
1472 NTSTATUS status = STATUS_SUCCESS;
1473 KS_EVENT_HANDLERS handlers;
1475 /* to make sure the address object is opened already */
1476 if (tconn->kstc_addr.FileObject == NULL) {
1480 /* initialize the handlers indictor array. for sender and listenr,
1481 there are different set of callbacks. for child, we just return. */
1483 memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
1485 SetEventHandler(handlers, TDI_EVENT_ERROR, KsErrorEventHandler);
1486 SetEventHandler(handlers, TDI_EVENT_DISCONNECT, KsDisconnectEventHandler);
1487 SetEventHandler(handlers, TDI_EVENT_RECEIVE, KsTcpReceiveEventHandler);
1488 SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, KsTcpReceiveExpeditedEventHandler);
1489 SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, KsTcpChainedReceiveEventHandler);
1491 // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, KsTcpChainedReceiveExpeditedEventHandler);
1493 if (tconn->kstc_type == kstt_listener) {
1494 SetEventHandler(handlers, TDI_EVENT_CONNECT, KsConnectEventHandler);
1495 } else if (tconn->kstc_type == kstt_child) {
1499 /* set all the event callbacks */
1500 status = KsSetEventHandlers(
1501 tconn->kstc_addr.FileObject, /* Address File Object */
1502 tconn, /* Event Context */
1503 &handlers /* Event callback handlers */
1508 return cfs_error_code(status);
1514 * disable all the event handler callbacks (set to NULL)
1517 * tconn: the tdi connecton object
1520 * int: ks error code
1528 ksock_tconn_t * tconn
1531 NTSTATUS status = STATUS_SUCCESS;
1532 KS_EVENT_HANDLERS handlers;
1534 /* to make sure the address object is opened already */
1535 if (tconn->kstc_addr.FileObject == NULL) {
1539 /* initialize the handlers indictor array. for sender and listenr,
1540 there are different set of callbacks. for child, we just return. */
1542 memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
1544 SetEventHandler(handlers, TDI_EVENT_ERROR, NULL);
1545 SetEventHandler(handlers, TDI_EVENT_DISCONNECT, NULL);
1546 SetEventHandler(handlers, TDI_EVENT_RECEIVE, NULL);
1547 SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, NULL);
1548 SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, NULL);
1549 // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, NULL);
1551 if (tconn->kstc_type == kstt_listener) {
1552 SetEventHandler(handlers, TDI_EVENT_CONNECT, NULL);
1553 } else if (tconn->kstc_type == kstt_child) {
1557 /* set all the event callbacks */
1558 status = KsSetEventHandlers(
1559 tconn->kstc_addr.FileObject, /* Address File Object */
1560 tconn, /* Event Context */
1561 &handlers /* Event callback handlers */
1566 return cfs_error_code(status);
1571 * KsAcceptCompletionRoutine
1572 * Irp completion routine for TdiBuildAccept (KsConnectEventHandler)
1574 * Here system gives us a chance to check the conneciton is built
1578 * DeviceObject: the device object of the transport driver
1579 * Irp: the Irp is being completed.
1580 * Context: the context we specified when issuing the Irp
1590 KsAcceptCompletionRoutine(
1591 IN PDEVICE_OBJECT DeviceObject,
1596 ksock_tconn_t * child = (ksock_tconn_t *) Context;
1597 ksock_tconn_t * parent = child->child.kstc_parent;
1599 KsPrint((2, "KsAcceptCompletionRoutine: called at Irql: %xh\n",
1600 KeGetCurrentIrql() ));
1602 KsPrint((2, "KsAcceptCompletionRoutine: Context = %xh Status = %xh\n",
1603 Context, Irp->IoStatus.Status));
1605 LASSERT(child->kstc_type == kstt_child);
1607 spin_lock(&(child->kstc_lock));
1609 LASSERT(parent->kstc_state == ksts_listening);
1610 LASSERT(child->kstc_state == ksts_connecting);
1612 if (NT_SUCCESS(Irp->IoStatus.Status)) {
1614 child->child.kstc_accepted = TRUE;
1616 child->kstc_state = ksts_connected;
1618 /* wake up the daemon thread which waits on this event */
1620 &(parent->listener.kstc_accept_event),
1625 spin_unlock(&(child->kstc_lock));
1627 KsPrint((2, "KsAcceptCompletionRoutine: Get %xh now signal the event ...\n", parent));
1631 /* re-use this child connecton */
1632 child->child.kstc_accepted = FALSE;
1633 child->child.kstc_busy = FALSE;
1634 child->kstc_state = ksts_associated;
1636 spin_unlock(&(child->kstc_lock));
1639 /* now free the Irp */
1642 /* drop the refer count of the child */
1643 ks_put_tconn(child);
1645 return (STATUS_MORE_PROCESSING_REQUIRED);
1650 * ks_get_vacancy_backlog
1651 * Get a vacancy listeing child from the backlog list
1654 * parent: the listener daemon connection
1657 * the child listening connection or NULL in failure
1660 * Parent's lock should be acquired before calling.
1664 ks_get_vacancy_backlog(
1665 ksock_tconn_t * parent
1668 ksock_tconn_t * child;
1670 LASSERT(parent->kstc_type == kstt_listener);
1671 LASSERT(parent->kstc_state == ksts_listening);
1673 if (list_empty(&(parent->listener.kstc_listening.list))) {
1679 struct list_head * tmp;
1681 /* check the listening queue and try to get a free connecton */
1683 list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
1684 child = list_entry (tmp, ksock_tconn_t, child.kstc_link);
1685 spin_lock(&(child->kstc_lock));
1687 if (!child->child.kstc_busy) {
1688 LASSERT(child->kstc_state == ksts_associated);
1689 child->child.kstc_busy = TRUE;
1690 spin_unlock(&(child->kstc_lock));
1693 spin_unlock(&(child->kstc_lock));
1703 KsSearchIpAddress(PUNICODE_STRING DeviceName)
1705 ks_addr_slot_t * slot = NULL;
1706 PLIST_ENTRY list = NULL;
1708 spin_lock(&ks_data.ksnd_addrs_lock);
1710 list = ks_data.ksnd_addrs_list.Flink;
1711 while (list != &ks_data.ksnd_addrs_list) {
1712 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
1713 if (RtlCompareUnicodeString(
1723 spin_unlock(&ks_data.ksnd_addrs_lock);
1729 KsCleanupIpAddresses()
1731 spin_lock(&ks_data.ksnd_addrs_lock);
1733 while (!IsListEmpty(&ks_data.ksnd_addrs_list)) {
1735 ks_addr_slot_t * slot = NULL;
1736 PLIST_ENTRY list = NULL;
1738 list = RemoveHeadList(&ks_data.ksnd_addrs_list);
1739 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
1741 ks_data.ksnd_naddrs--;
1744 cfs_assert(ks_data.ksnd_naddrs == 0);
1745 spin_unlock(&ks_data.ksnd_addrs_lock);
1749 KsAddAddressHandler(
1750 IN PTA_ADDRESS Address,
1751 IN PUNICODE_STRING DeviceName,
1752 IN PTDI_PNP_CONTEXT Context
1755 PTDI_ADDRESS_IP IpAddress = NULL;
1757 if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
1758 Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
1760 ks_addr_slot_t * slot = NULL;
1762 IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
1763 KsPrint((1, "KsAddAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
1764 DeviceName, Context, IpAddress->in_addr,
1765 (IpAddress->in_addr & 0xFF000000) >> 24,
1766 (IpAddress->in_addr & 0x00FF0000) >> 16,
1767 (IpAddress->in_addr & 0x0000FF00) >> 8,
1768 (IpAddress->in_addr & 0x000000FF) >> 0 ));
1770 slot = KsSearchIpAddress(DeviceName);
1774 slot->ip_addr = ntohl(IpAddress->in_addr);
1776 slot = cfs_alloc(sizeof(ks_addr_slot_t) + DeviceName->Length, CFS_ALLOC_ZERO);
1778 spin_lock(&ks_data.ksnd_addrs_lock);
1779 InsertTailList(&ks_data.ksnd_addrs_list, &slot->link);
1780 sprintf(slot->iface, "eth%d", ks_data.ksnd_naddrs++);
1781 slot->ip_addr = ntohl(IpAddress->in_addr);
1783 RtlMoveMemory(&slot->buffer[0], DeviceName->Buffer, DeviceName->Length);
1784 slot->devname.Length = DeviceName->Length;
1785 slot->devname.MaximumLength = DeviceName->Length + sizeof(WCHAR);
1786 slot->devname.Buffer = slot->buffer;
1787 spin_unlock(&ks_data.ksnd_addrs_lock);
1794 KsDelAddressHandler(
1795 IN PTA_ADDRESS Address,
1796 IN PUNICODE_STRING DeviceName,
1797 IN PTDI_PNP_CONTEXT Context
1800 PTDI_ADDRESS_IP IpAddress = NULL;
1802 if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
1803 Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
1805 ks_addr_slot_t * slot = NULL;
1807 slot = KsSearchIpAddress(DeviceName);
1813 IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
1814 KsPrint((1, "KsDelAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
1815 DeviceName, Context, IpAddress->in_addr,
1816 (IpAddress->in_addr & 0xFF000000) >> 24,
1817 (IpAddress->in_addr & 0x00FF0000) >> 16,
1818 (IpAddress->in_addr & 0x0000FF00) >> 8,
1819 (IpAddress->in_addr & 0x000000FF) >> 0 ));
1824 KsRegisterPnpHandlers()
1826 TDI20_CLIENT_INTERFACE_INFO ClientInfo;
1828 /* initialize the global ks_data members */
1829 RtlInitUnicodeString(&ks_data.ksnd_client_name, TDILND_MODULE_NAME);
1830 spin_lock_init(&ks_data.ksnd_addrs_lock);
1831 InitializeListHead(&ks_data.ksnd_addrs_list);
1833 /* register the pnp handlers */
1834 RtlZeroMemory(&ClientInfo, sizeof(ClientInfo));
1835 ClientInfo.TdiVersion = TDI_CURRENT_VERSION;
1837 ClientInfo.ClientName = &ks_data.ksnd_client_name;
1838 ClientInfo.AddAddressHandlerV2 = KsAddAddressHandler;
1839 ClientInfo.DelAddressHandlerV2 = KsDelAddressHandler;
1841 return TdiRegisterPnPHandlers(&ClientInfo, sizeof(ClientInfo),
1842 &ks_data.ksnd_pnp_handle);
1846 KsDeregisterPnpHandlers()
1848 if (ks_data.ksnd_pnp_handle) {
1850 /* De-register the pnp handlers */
1852 TdiDeregisterPnPHandlers(ks_data.ksnd_pnp_handle);
1853 ks_data.ksnd_pnp_handle = NULL;
1855 /* cleanup all the ip address slots */
1856 KsCleanupIpAddresses();
1861 * KsConnectEventHandler
1862 * Connect event handler event handler, called by the underlying TDI
1863 * transport in response to an incoming request to the listening daemon.
1865 * it will grab a vacancy backlog from the children tconn list, and
1866 * build an acception Irp with it, then transfer the Irp to TDI driver.
1869 * TdiEventContext: the tdi connnection object of the listening daemon
1873 * Nt kernel status code
1880 KsConnectEventHandler(
1881 IN PVOID TdiEventContext,
1882 IN LONG RemoteAddressLength,
1883 IN PVOID RemoteAddress,
1884 IN LONG UserDataLength,
1886 IN LONG OptionsLength,
1888 OUT CONNECTION_CONTEXT * ConnectionContext,
1889 OUT PIRP * AcceptIrp
1892 ksock_tconn_t * parent;
1893 ksock_tconn_t * child;
1895 PFILE_OBJECT FileObject;
1896 PDEVICE_OBJECT DeviceObject;
1900 PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
1902 KsPrint((2,"KsConnectEventHandler: call at Irql: %u\n", KeGetCurrentIrql()));
1903 parent = (ksock_tconn_t *) TdiEventContext;
1905 LASSERT(parent->kstc_type == kstt_listener);
1907 spin_lock(&(parent->kstc_lock));
1909 if (parent->kstc_state == ksts_listening) {
1911 /* allocate a new ConnectionInfo to backup the peer's info */
1913 ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
1914 NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) +
1915 RemoteAddressLength, 'iCsK' );
1917 if (NULL == ConnectionInfo) {
1919 Status = STATUS_INSUFFICIENT_RESOURCES;
1920 cfs_enter_debugger();
1924 /* initializing ConnectionInfo structure ... */
1926 ConnectionInfo->UserDataLength = UserDataLength;
1927 ConnectionInfo->UserData = UserData;
1928 ConnectionInfo->OptionsLength = OptionsLength;
1929 ConnectionInfo->Options = Options;
1930 ConnectionInfo->RemoteAddressLength = RemoteAddressLength;
1931 ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
1934 ConnectionInfo->RemoteAddress,
1939 /* get the vacancy listening child tdi connections */
1941 child = ks_get_vacancy_backlog(parent);
1945 spin_lock(&(child->kstc_lock));
1946 child->child.kstc_info.ConnectionInfo = ConnectionInfo;
1947 child->child.kstc_info.Remote = ConnectionInfo->RemoteAddress;
1948 child->kstc_state = ksts_connecting;
1949 spin_unlock(&(child->kstc_lock));
1953 KsPrint((2, "KsConnectEventHandler: No enough backlogs: Refsued the connectio: %xh\n", parent));
1955 Status = STATUS_INSUFFICIENT_RESOURCES;
1960 FileObject = child->child.kstc_info.FileObject;
1961 DeviceObject = IoGetRelatedDeviceObject (FileObject);
1963 Irp = KsBuildTdiIrp(DeviceObject);
1969 KsAcceptCompletionRoutine,
1975 IoSetNextIrpStackLocation(Irp);
1977 /* grap the refer of the child tdi connection */
1978 ks_get_tconn(child);
1980 Status = STATUS_MORE_PROCESSING_REQUIRED;
1983 *ConnectionContext = child;
1987 Status = STATUS_CONNECTION_REFUSED;
1991 spin_unlock(&(parent->kstc_lock));
1997 spin_unlock(&(parent->kstc_lock));
2001 *ConnectionContext = NULL;
2003 if (ConnectionInfo) {
2005 ExFreePool(ConnectionInfo);
2018 * KsDisconnectCompletionRoutine
2019 * the Irp completion routine for TdiBuildDisconect
2021 * We just signal the event and return MORE_PRO... to
2022 * let the caller take the responsibility of the Irp.
2025 * DeviceObject: the device object of the transport
2026 * Irp: the Irp is being completed.
2027 * Context: the event specified by the caller
2037 KsDisconectCompletionRoutine (
2038 IN PDEVICE_OBJECT DeviceObject,
2044 KeSetEvent((PKEVENT) Context, 0, FALSE);
2046 return STATUS_MORE_PROCESSING_REQUIRED;
2048 UNREFERENCED_PARAMETER(DeviceObject);
2053 * KsDisconnectHelper
2054 * the routine to be executed in the WorkItem procedure
2055 * this routine is to disconnect a tdi connection
2058 * Workitem: the context transferred to the workitem
2064 * tconn is already referred in abort_connecton ...
2068 KsDisconnectHelper(PKS_DISCONNECT_WORKITEM WorkItem)
2070 ksock_tconn_t * tconn = WorkItem->tconn;
2072 DbgPrint("KsDisconnectHelper: disconnecting tconn=%p\n", tconn);
2073 ks_disconnect_tconn(tconn, WorkItem->Flags);
2075 KeSetEvent(&(WorkItem->Event), 0, FALSE);
2077 spin_lock(&(tconn->kstc_lock));
2078 cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
2079 spin_unlock(&(tconn->kstc_lock));
2080 ks_put_tconn(tconn);
2085 * KsDisconnectEventHandler
2086 * Disconnect event handler event handler, called by the underlying TDI transport
2087 * in response to an incoming disconnection notification from a remote node.
2090 * ConnectionContext: tdi connnection object
2091 * DisconnectFlags: specifies the nature of the disconnection
2095 * Nt kernel status code
2103 KsDisconnectEventHandler(
2104 IN PVOID TdiEventContext,
2105 IN CONNECTION_CONTEXT ConnectionContext,
2106 IN LONG DisconnectDataLength,
2107 IN PVOID DisconnectData,
2108 IN LONG DisconnectInformationLength,
2109 IN PVOID DisconnectInformation,
2110 IN ULONG DisconnectFlags
2113 ksock_tconn_t * tconn;
2115 PKS_DISCONNECT_WORKITEM WorkItem;
2117 tconn = (ksock_tconn_t *)ConnectionContext;
2119 KsPrint((2, "KsTcpDisconnectEventHandler: called at Irql: %xh\n",
2120 KeGetCurrentIrql() ));
2122 KsPrint((2, "tconn = %x DisconnectFlags= %xh\n",
2123 tconn, DisconnectFlags));
2125 ks_get_tconn(tconn);
2126 spin_lock(&(tconn->kstc_lock));
2128 WorkItem = &(tconn->kstc_disconnect);
2130 if (tconn->kstc_state != ksts_connected) {
2132 Status = STATUS_SUCCESS;
2136 if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_ABORT)) {
2138 Status = STATUS_REMOTE_DISCONNECT;
2140 } else if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_RELEASE)) {
2142 Status = STATUS_GRACEFUL_DISCONNECT;
2145 if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
2147 ks_get_tconn(tconn);
2149 WorkItem->Flags = DisconnectFlags;
2150 WorkItem->tconn = tconn;
2152 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
2154 /* queue the workitem to call */
2155 ExQueueWorkItem(&(WorkItem->WorkItem), DelayedWorkQueue);
2159 spin_unlock(&(tconn->kstc_lock));
2160 ks_put_tconn(tconn);
2166 KsTcpReceiveCompletionRoutine(
2168 IN PKS_TCP_COMPLETION_CONTEXT Context
2171 NTSTATUS Status = Irp->IoStatus.Status;
2173 if (NT_SUCCESS(Status)) {
2175 ksock_tconn_t *tconn = Context->tconn;
2177 PKS_TSDU_DAT KsTsduDat = Context->CompletionContext;
2178 PKS_TSDU_BUF KsTsduBuf = Context->CompletionContext;
2180 KsPrint((1, "KsTcpReceiveCompletionRoutine: Total %xh bytes.\n",
2181 Context->KsTsduMgr->TotalBytes ));
2183 spin_lock(&(tconn->kstc_lock));
2185 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
2186 if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
2187 cfs_clear_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
2189 cfs_enter_debugger();
2192 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
2193 if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
2194 cfs_clear_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
2196 cfs_enter_debugger();
2200 spin_unlock(&(tconn->kstc_lock));
2202 /* wake up the thread waiting for the completion of this Irp */
2203 KeSetEvent(Context->Event, 0, FALSE);
2205 /* re-active the ks connection and wake up the scheduler */
2206 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2207 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2208 Context->KsTsduMgr->TotalBytes );
2213 /* un-expected errors occur, we must abort the connection */
2214 ks_abort_tconn(Context->tconn);
2219 /* Freeing the Context structure... */
2220 ExFreePool(Context);
2235 * KsTcpCompletionRoutine
2236 * the Irp completion routine for TdiBuildSend and TdiBuildReceive ...
2237 * We need call the use's own CompletionRoutine if specified. Or
2238 * it's a synchronous case, we need signal the event.
2241 * DeviceObject: the device object of the transport
2242 * Irp: the Irp is being completed.
2243 * Context: the context we specified when issuing the Irp
2253 KsTcpCompletionRoutine(
2254 IN PDEVICE_OBJECT DeviceObject,
2261 PKS_TCP_COMPLETION_CONTEXT CompletionContext = NULL;
2262 ksock_tconn_t * tconn = NULL;
2264 CompletionContext = (PKS_TCP_COMPLETION_CONTEXT) Context;
2265 tconn = CompletionContext->tconn;
2267 /* release the chained mdl */
2268 KsReleaseMdl(Irp->MdlAddress, FALSE);
2269 Irp->MdlAddress = NULL;
2271 if (CompletionContext->CompletionRoutine) {
2273 if ( CompletionContext->bCounted &&
2274 InterlockedDecrement(&CompletionContext->ReferCount) != 0 ) {
2279 // Giving control to user specified CompletionRoutine ...
2282 CompletionContext->CompletionRoutine(
2290 // Signaling the Event ...
2293 KeSetEvent(CompletionContext->Event, 0, FALSE);
2296 /* drop the reference count of the tconn object */
2297 ks_put_tconn(tconn);
2301 cfs_enter_debugger();
2306 return STATUS_MORE_PROCESSING_REQUIRED;
2310 * KsTcpSendCompletionRoutine
2311 * the user specified Irp completion routine for asynchronous
2312 * data transmission requests.
2314 * It will do th cleanup job of the ksock_tx_t and wake up the
2315 * ks scheduler thread
2318 * Irp: the Irp is being completed.
2319 * Context: the context we specified when issuing the Irp
2329 KsTcpSendCompletionRoutine(
2331 IN PKS_TCP_COMPLETION_CONTEXT Context
2334 NTSTATUS Status = Irp->IoStatus.Status;
2335 ULONG rc = Irp->IoStatus.Information;
2336 ksock_tconn_t * tconn = Context->tconn;
2337 PKS_TSDUMGR KsTsduMgr = Context->KsTsduMgr;
2343 if (NT_SUCCESS(Status)) {
2345 if (Context->bCounted) {
2346 PVOID tx = Context->CompletionContext;
2348 ASSERT(tconn->kstc_update_tx != NULL);
2350 /* update the tx, rebasing the kiov or iov pointers */
2351 tx = tconn->kstc_update_tx(tconn, tx, rc);
2353 /* update the KsTsudMgr total bytes */
2354 spin_lock(&tconn->kstc_lock);
2355 KsTsduMgr->TotalBytes -= rc;
2356 spin_unlock(&tconn->kstc_lock);
2359 * now it's time to re-queue the conns into the
2360 * scheduler queue and wake the scheduler thread.
2363 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2364 tconn->kstc_sched_cb( tconn, TRUE, tx, 0);
2369 PKS_TSDU KsTsdu = Context->CompletionContext;
2370 PKS_TSDU_BUF KsTsduBuf = Context->CompletionContext2;
2371 PKS_TSDU_DAT KsTsduDat = Context->CompletionContext2;
2373 spin_lock(&tconn->kstc_lock);
2374 /* This is bufferred sending ... */
2375 ASSERT(KsTsduBuf->StartOffset == 0);
2377 if (KsTsduBuf->DataLength > Irp->IoStatus.Information) {
2378 /* not fully sent .... we have to abort the connection */
2379 spin_unlock(&tconn->kstc_lock);
2380 ks_abort_tconn(tconn);
2384 if (KsTsduBuf->TsduType == TSDU_TYPE_BUF) {
2385 /* free the buffer */
2386 ExFreePool(KsTsduBuf->UserBuffer);
2387 KsTsduMgr->TotalBytes -= KsTsduBuf->DataLength;
2388 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
2389 } else if (KsTsduDat->TsduType == TSDU_TYPE_DAT) {
2390 KsTsduMgr->TotalBytes -= KsTsduDat->DataLength;
2391 KsTsdu->StartOffset += KsTsduDat->TotalLength;
2393 cfs_enter_debugger(); /* shoult not get here */
2396 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
2398 list_del(&KsTsdu->Link);
2399 KsTsduMgr->NumOfTsdu--;
2400 KsPutKsTsdu(KsTsdu);
2403 spin_unlock(&tconn->kstc_lock);
2408 /* cfs_enter_debugger(); */
2411 * for the case that the transmission is ussuccessful,
2412 * we need abort the tdi connection, but not destroy it.
2413 * the socknal conn will drop the refer count, then the
2414 * tdi connection will be freed.
2417 ks_abort_tconn(tconn);
2422 /* freeing the Context structure... */
2425 ExFreePool(Context);
2429 /* it's our duty to free the Irp. */
2442 * Normal receive event handler
2444 * It will move data from system Tsdu to our TsduList
2448 KsTcpReceiveEventHandler(
2449 IN PVOID TdiEventContext,
2450 IN CONNECTION_CONTEXT ConnectionContext,
2451 IN ULONG ReceiveFlags,
2452 IN ULONG BytesIndicated,
2453 IN ULONG BytesAvailable,
2454 OUT ULONG * BytesTaken,
2456 OUT PIRP * IoRequestPacket
2461 ksock_tconn_t * tconn;
2464 PKS_TSDUMGR KsTsduMgr;
2466 PKS_TSDU_DAT KsTsduDat;
2467 PKS_TSDU_BUF KsTsduBuf;
2469 BOOLEAN bIsExpedited;
2470 BOOLEAN bIsCompleteTsdu;
2472 BOOLEAN bNewTsdu = FALSE;
2473 BOOLEAN bNewBuff = FALSE;
2475 PCHAR Buffer = NULL;
2479 PFILE_OBJECT FileObject;
2480 PDEVICE_OBJECT DeviceObject;
2482 ULONG BytesReceived = 0;
2484 PKS_TCP_COMPLETION_CONTEXT context = NULL;
2487 tconn = (ksock_tconn_t *) ConnectionContext;
2489 ks_get_tconn(tconn);
2491 /* check whether the whole body of payload is received or not */
2492 if ( (cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_ENTIRE_MESSAGE)) &&
2493 (BytesIndicated == BytesAvailable) ) {
2494 bIsCompleteTsdu = TRUE;
2496 bIsCompleteTsdu = FALSE;
2499 bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
2501 KsPrint((2, "KsTcpReceiveEventHandler BytesIndicated = %d BytesAvailable = %d ...\n", BytesIndicated, BytesAvailable));
2502 KsPrint((2, "bIsCompleteTsdu = %d bIsExpedited = %d\n", bIsCompleteTsdu, bIsExpedited ));
2504 spin_lock(&(tconn->kstc_lock));
2506 /* check whether we are conntected or not listener ¡Â*/
2507 if ( !((tconn->kstc_state == ksts_connected) &&
2508 (tconn->kstc_type == kstt_sender ||
2509 tconn->kstc_type == kstt_child))) {
2511 *BytesTaken = BytesIndicated;
2513 spin_unlock(&(tconn->kstc_lock));
2514 ks_put_tconn(tconn);
2516 return (STATUS_SUCCESS);
2519 if (tconn->kstc_type == kstt_sender) {
2520 KsChain = &(tconn->sender.kstc_recv);
2522 LASSERT(tconn->kstc_type == kstt_child);
2523 KsChain = &(tconn->child.kstc_recv);
2527 KsTsduMgr = &(KsChain->Expedited);
2529 KsTsduMgr = &(KsChain->Normal);
2532 /* if the Tsdu is even larger than the biggest Tsdu, we have
2533 to allocate new buffer and use TSDU_TYOE_BUF to store it */
2535 if ( KS_TSDU_STRU_SIZE(BytesAvailable) > ks_data.ksnd_tsdu_size -
2536 KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
2540 /* retrieve the latest Tsdu buffer form TsduMgr
2541 list if the list is not empty. */
2543 if (list_empty(&(KsTsduMgr->TsduList))) {
2545 LASSERT(KsTsduMgr->NumOfTsdu == 0);
2550 LASSERT(KsTsduMgr->NumOfTsdu > 0);
2551 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
2553 /* if this Tsdu does not contain enough space, we need
2554 allocate a new Tsdu queue. */
2557 if ( KsTsdu->LastOffset + sizeof(KS_TSDU_BUF) >
2558 KsTsdu->TotalLength ) {
2562 if ( KS_TSDU_STRU_SIZE(BytesAvailable) >
2563 KsTsdu->TotalLength - KsTsdu->LastOffset ) {
2569 /* allocating the buffer for TSDU_TYPE_BUF */
2571 Buffer = ExAllocatePool(NonPagedPool, BytesAvailable);
2572 if (NULL == Buffer) {
2573 /* there's no enough memory for us. We just try to
2574 receive maximum bytes with a new Tsdu */
2580 /* allocate a new Tsdu in case we are not statisfied. */
2582 if (NULL == KsTsdu) {
2584 KsTsdu = KsAllocateKsTsdu();
2586 if (NULL == KsTsdu) {
2593 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2594 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2598 /* setup up the KS_TSDU_BUF record */
2600 KsTsduBuf->TsduType = TSDU_TYPE_BUF;
2601 KsTsduBuf->TsduFlags = 0;
2602 KsTsduBuf->StartOffset = 0;
2603 KsTsduBuf->UserBuffer = Buffer;
2604 KsTsduBuf->DataLength = BytesReceived = BytesAvailable;
2606 KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
2610 /* setup the KS_TSDU_DATA to contain all the messages */
2612 KsTsduDat->TsduType = TSDU_TYPE_DAT;
2613 KsTsduDat->TsduFlags = 0;
2615 if ( KsTsdu->TotalLength - KsTsdu->LastOffset >=
2616 KS_TSDU_STRU_SIZE(BytesAvailable) ) {
2617 BytesReceived = BytesAvailable;
2619 BytesReceived = KsTsdu->TotalLength - KsTsdu->LastOffset -
2620 FIELD_OFFSET(KS_TSDU_DAT, Data);
2621 BytesReceived &= (~((ULONG)3));
2623 KsTsduDat->DataLength = BytesReceived;
2624 KsTsduDat->TotalLength = KS_TSDU_STRU_SIZE(BytesReceived);
2625 KsTsduDat->StartOffset = 0;
2627 Buffer = &KsTsduDat->Data[0];
2629 KsTsdu->LastOffset += KsTsduDat->TotalLength;
2632 KsTsduMgr->TotalBytes += BytesReceived;
2634 if (bIsCompleteTsdu) {
2636 /* It's a complete receive, we just move all
2637 the data from system to our Tsdu */
2645 *BytesTaken = BytesReceived;
2646 Status = STATUS_SUCCESS;
2649 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2650 KsTsduMgr->NumOfTsdu++;
2653 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
2655 /* re-active the ks connection and wake up the scheduler */
2656 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2657 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2658 KsTsduMgr->TotalBytes );
2663 /* there's still data in tdi internal queue, we need issue a new
2664 Irp to receive all of them. first allocate the tcp context */
2666 context = ExAllocatePoolWithTag(
2668 sizeof(KS_TCP_COMPLETION_CONTEXT),
2673 Status = STATUS_INSUFFICIENT_RESOURCES;
2677 /* setup the context */
2678 RtlZeroMemory(context, sizeof(KS_TCP_COMPLETION_CONTEXT));
2680 context->tconn = tconn;
2681 context->CompletionRoutine = KsTcpReceiveCompletionRoutine;
2682 context->CompletionContext = KsTsdu;
2683 context->CompletionContext = bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat;
2684 context->KsTsduMgr = KsTsduMgr;
2685 context->Event = &(KsTsduMgr->Event);
2687 if (tconn->kstc_type == kstt_sender) {
2688 FileObject = tconn->sender.kstc_info.FileObject;
2690 FileObject = tconn->child.kstc_info.FileObject;
2693 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2695 /* build new tdi Irp and setup it. */
2696 Irp = KsBuildTdiIrp(DeviceObject);
2702 Status = KsLockUserBuffer(
2710 if (!NT_SUCCESS(Status)) {
2718 KsTcpCompletionRoutine,
2721 ReceiveFlags & (TDI_RECEIVE_NORMAL | TDI_RECEIVE_EXPEDITED),
2725 IoSetNextIrpStackLocation(Irp);
2727 /* return the newly built Irp to transport driver,
2728 it will process it to receive all the data */
2730 *IoRequestPacket = Irp;
2735 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2736 KsTsduMgr->NumOfTsdu++;
2740 cfs_set_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
2742 cfs_set_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
2744 ks_get_tconn(tconn);
2745 Status = STATUS_MORE_PROCESSING_REQUIRED;
2748 spin_unlock(&(tconn->kstc_lock));
2749 ks_put_tconn(tconn);
2755 spin_unlock(&(tconn->kstc_lock));
2757 if (bNewTsdu && (KsTsdu != NULL)) {
2758 KsFreeKsTsdu(KsTsdu);
2762 KsReleaseMdl(Mdl, FALSE);
2770 ExFreePool(context);
2773 ks_abort_tconn(tconn);
2774 ks_put_tconn(tconn);
2776 *BytesTaken = BytesAvailable;
2777 Status = STATUS_SUCCESS;
2783 * Expedited receive event handler
2787 KsTcpReceiveExpeditedEventHandler(
2788 IN PVOID TdiEventContext,
2789 IN CONNECTION_CONTEXT ConnectionContext,
2790 IN ULONG ReceiveFlags,
2791 IN ULONG BytesIndicated,
2792 IN ULONG BytesAvailable,
2793 OUT ULONG * BytesTaken,
2795 OUT PIRP * IoRequestPacket
2798 return KsTcpReceiveEventHandler(
2801 ReceiveFlags | TDI_RECEIVE_EXPEDITED,
2812 * Bulk receive event handler
2814 * It will queue all the system Tsdus to our TsduList.
2815 * Then later ks_recv_mdl will release them.
2819 KsTcpChainedReceiveEventHandler (
2820 IN PVOID TdiEventContext, // the event context
2821 IN CONNECTION_CONTEXT ConnectionContext,
2822 IN ULONG ReceiveFlags,
2823 IN ULONG ReceiveLength,
2824 IN ULONG StartingOffset, // offset of start of client data in TSDU
2825 IN PMDL Tsdu, // TSDU data chain
2826 IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives
2832 ksock_tconn_t * tconn;
2835 PKS_TSDUMGR KsTsduMgr;
2837 PKS_TSDU_MDL KsTsduMdl;
2839 BOOLEAN bIsExpedited;
2840 BOOLEAN bNewTsdu = FALSE;
2842 tconn = (ksock_tconn_t *) ConnectionContext;
2844 bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
2846 KsPrint((2, "KsTcpChainedReceive: ReceiveLength = %xh bIsExpedited = %d\n", ReceiveLength, bIsExpedited));
2848 ks_get_tconn(tconn);
2849 spin_lock(&(tconn->kstc_lock));
2851 /* check whether we are conntected or not listener ¡Â*/
2852 if ( !((tconn->kstc_state == ksts_connected) &&
2853 (tconn->kstc_type == kstt_sender ||
2854 tconn->kstc_type == kstt_child))) {
2856 spin_unlock(&(tconn->kstc_lock));
2857 ks_put_tconn(tconn);
2859 return (STATUS_SUCCESS);
2862 /* get the latest Tsdu buffer form TsduMgr list.
2863 just set NULL if the list is empty. */
2865 if (tconn->kstc_type == kstt_sender) {
2866 KsChain = &(tconn->sender.kstc_recv);
2868 LASSERT(tconn->kstc_type == kstt_child);
2869 KsChain = &(tconn->child.kstc_recv);
2873 KsTsduMgr = &(KsChain->Expedited);
2875 KsTsduMgr = &(KsChain->Normal);
2878 if (list_empty(&(KsTsduMgr->TsduList))) {
2880 LASSERT(KsTsduMgr->NumOfTsdu == 0);
2885 LASSERT(KsTsduMgr->NumOfTsdu > 0);
2886 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
2887 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
2889 if (sizeof(KS_TSDU_MDL) > KsTsdu->TotalLength - KsTsdu->LastOffset) {
2894 /* if there's no Tsdu or the free size is not enough for this
2895 KS_TSDU_MDL structure. We need re-allocate a new Tsdu. */
2897 if (NULL == KsTsdu) {
2899 KsTsdu = KsAllocateKsTsdu();
2901 if (NULL == KsTsdu) {
2908 /* just queue the KS_TSDU_MDL to the Tsdu buffer */
2910 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2912 KsTsduMdl->TsduType = TSDU_TYPE_MDL;
2913 KsTsduMdl->DataLength = ReceiveLength;
2914 KsTsduMdl->StartOffset = StartingOffset;
2915 KsTsduMdl->Mdl = Tsdu;
2916 KsTsduMdl->Descriptor = TsduDescriptor;
2918 KsTsdu->LastOffset += sizeof(KS_TSDU_MDL);
2919 KsTsduMgr->TotalBytes += ReceiveLength;
2921 KsPrint((2, "KsTcpChainedReceiveEventHandler: Total %xh bytes.\n",
2922 KsTsduMgr->TotalBytes ));
2924 Status = STATUS_PENDING;
2926 /* attach it to the TsduMgr list if the Tsdu is newly created. */
2929 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2930 KsTsduMgr->NumOfTsdu++;
2933 spin_unlock(&(tconn->kstc_lock));
2935 /* wake up the threads waiing in ks_recv_mdl */
2936 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
2938 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2939 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2940 KsTsduMgr->TotalBytes );
2943 ks_put_tconn(tconn);
2945 /* Return STATUS_PENDING to system because we are still
2946 owning the MDL resources. ks_recv_mdl is expected
2947 to free the MDL resources. */
2953 spin_unlock(&(tconn->kstc_lock));
2955 if (bNewTsdu && (KsTsdu != NULL)) {
2956 KsFreeKsTsdu(KsTsdu);
2959 /* abort the tdi connection */
2960 ks_abort_tconn(tconn);
2961 ks_put_tconn(tconn);
2964 Status = STATUS_SUCCESS;
2971 * Expedited & Bulk receive event handler
2975 KsTcpChainedReceiveExpeditedEventHandler (
2976 IN PVOID TdiEventContext, // the event context
2977 IN CONNECTION_CONTEXT ConnectionContext,
2978 IN ULONG ReceiveFlags,
2979 IN ULONG ReceiveLength,
2980 IN ULONG StartingOffset, // offset of start of client data in TSDU
2981 IN PMDL Tsdu, // TSDU data chain
2982 IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives
2985 return KsTcpChainedReceiveEventHandler(
2988 ReceiveFlags | TDI_RECEIVE_EXPEDITED,
2997 KsPrintProviderInfo(
2999 PTDI_PROVIDER_INFO ProviderInfo
3002 KsPrint((2, "%ws ProviderInfo:\n", DeviceName));
3004 KsPrint((2, " Version : 0x%4.4X\n", ProviderInfo->Version ));
3005 KsPrint((2, " MaxSendSize : %d\n", ProviderInfo->MaxSendSize ));
3006 KsPrint((2, " MaxConnectionUserData: %d\n", ProviderInfo->MaxConnectionUserData ));
3007 KsPrint((2, " MaxDatagramSize : %d\n", ProviderInfo->MaxDatagramSize ));
3008 KsPrint((2, " ServiceFlags : 0x%8.8X\n", ProviderInfo->ServiceFlags ));
3010 if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTION_MODE) {
3011 KsPrint((2, " CONNECTION_MODE\n"));
3014 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ORDERLY_RELEASE) {
3015 KsPrint((2, " ORDERLY_RELEASE\n"));
3018 if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTIONLESS_MODE) {
3019 KsPrint((2, " CONNECTIONLESS_MODE\n"));
3022 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ERROR_FREE_DELIVERY) {
3023 KsPrint((2, " ERROR_FREE_DELIVERY\n"));
3026 if( ProviderInfo->ServiceFlags & TDI_SERVICE_SECURITY_LEVEL ) {
3027 KsPrint((2, " SECURITY_LEVEL\n"));
3030 if (ProviderInfo->ServiceFlags & TDI_SERVICE_BROADCAST_SUPPORTED) {
3031 KsPrint((2, " BROADCAST_SUPPORTED\n"));
3034 if (ProviderInfo->ServiceFlags & TDI_SERVICE_MULTICAST_SUPPORTED) {
3035 KsPrint((2, " MULTICAST_SUPPORTED\n"));
3038 if (ProviderInfo->ServiceFlags & TDI_SERVICE_DELAYED_ACCEPTANCE) {
3039 KsPrint((2, " DELAYED_ACCEPTANCE\n"));
3042 if (ProviderInfo->ServiceFlags & TDI_SERVICE_EXPEDITED_DATA) {
3043 KsPrint((2, " EXPEDITED_DATA\n"));
3046 if( ProviderInfo->ServiceFlags & TDI_SERVICE_INTERNAL_BUFFERING) {
3047 KsPrint((2, " INTERNAL_BUFFERING\n"));
3050 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ROUTE_DIRECTED) {
3051 KsPrint((2, " ROUTE_DIRECTED\n"));
3054 if (ProviderInfo->ServiceFlags & TDI_SERVICE_NO_ZERO_LENGTH) {
3055 KsPrint((2, " NO_ZERO_LENGTH\n"));
3058 if (ProviderInfo->ServiceFlags & TDI_SERVICE_POINT_TO_POINT) {
3059 KsPrint((2, " POINT_TO_POINT\n"));
3062 if (ProviderInfo->ServiceFlags & TDI_SERVICE_MESSAGE_MODE) {
3063 KsPrint((2, " MESSAGE_MODE\n"));
3066 if (ProviderInfo->ServiceFlags & TDI_SERVICE_HALF_DUPLEX) {
3067 KsPrint((2, " HALF_DUPLEX\n"));
3070 KsPrint((2, " MinimumLookaheadData : %d\n", ProviderInfo->MinimumLookaheadData ));
3071 KsPrint((2, " MaximumLookaheadData : %d\n", ProviderInfo->MaximumLookaheadData ));
3072 KsPrint((2, " NumberOfResources : %d\n", ProviderInfo->NumberOfResources ));
3078 * Reuse a Tsdu from the freelist or allocate a new Tsdu
3079 * from the LookAsideList table or the NonPagedPool
3085 * PKS_Tsdu: the new Tsdu or NULL if it fails
3094 PKS_TSDU KsTsdu = NULL;
3096 spin_lock(&(ks_data.ksnd_tsdu_lock));
3098 if (!list_empty (&(ks_data.ksnd_freetsdus))) {
3100 LASSERT(ks_data.ksnd_nfreetsdus > 0);
3102 KsTsdu = list_entry(ks_data.ksnd_freetsdus.next, KS_TSDU, Link);
3103 list_del(&(KsTsdu->Link));
3104 ks_data.ksnd_nfreetsdus--;
3108 KsTsdu = (PKS_TSDU) cfs_mem_cache_alloc(
3109 ks_data.ksnd_tsdu_slab, 0);
3112 spin_unlock(&(ks_data.ksnd_tsdu_lock));
3114 if (NULL != KsTsdu) {
3115 KsInitializeKsTsdu(KsTsdu, ks_data.ksnd_tsdu_size);
3124 * Move the Tsdu to the free tsdu list in ks_data.
3127 * KsTsdu: Tsdu to be moved.
3141 spin_lock(&(ks_data.ksnd_tsdu_lock));
3143 list_add_tail( &(KsTsdu->Link), &(ks_data.ksnd_freetsdus));
3144 ks_data.ksnd_nfreetsdus++;
3146 spin_unlock(&(ks_data.ksnd_tsdu_lock));
3152 * Release a Tsdu: uninitialize then free it.
3155 * KsTsdu: Tsdu to be freed.
3170 ks_data.ksnd_tsdu_slab,
3176 * KsInitializeKsTsdu
3177 * Initialize the Tsdu buffer header
3180 * KsTsdu: the Tsdu to be initialized
3181 * Length: the total length of the Tsdu
3196 RtlZeroMemory(KsTsdu, Length);
3197 KsTsdu->Magic = KS_TSDU_MAGIC;
3198 KsTsdu->TotalLength = Length;
3199 KsTsdu->StartOffset = KsTsdu->LastOffset =
3200 KS_DWORD_ALIGN(sizeof(KS_TSDU));
3205 * KsInitializeKsTsduMgr
3206 * Initialize the management structure of
3210 * TsduMgr: the TsduMgr to be initialized
3220 KsInitializeKsTsduMgr(
3231 &(TsduMgr->TsduList)
3234 TsduMgr->NumOfTsdu = 0;
3235 TsduMgr->TotalBytes = 0;
3240 * KsInitializeKsChain
3241 * Initialize the China structure for receiving
3245 * KsChain: the KsChain to be initialized
3255 KsInitializeKsChain(
3259 KsInitializeKsTsduMgr(&(KsChain->Normal));
3260 KsInitializeKsTsduMgr(&(KsChain->Expedited));
3266 * Clean up all the Tsdus in the TsduMgr list
3269 * KsTsduMgr: the Tsdu list manager
3272 * NTSTATUS: nt status code
3280 PKS_TSDUMGR KsTsduMgr
3284 PKS_TSDU_DAT KsTsduDat;
3285 PKS_TSDU_BUF KsTsduBuf;
3286 PKS_TSDU_MDL KsTsduMdl;
3288 LASSERT(NULL != KsTsduMgr);
3290 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
3292 while (!list_empty(&KsTsduMgr->TsduList)) {
3294 KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
3295 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
3297 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
3300 // KsTsdu is empty now, we need free it ...
3303 list_del(&(KsTsdu->Link));
3304 KsTsduMgr->NumOfTsdu--;
3306 KsFreeKsTsdu(KsTsdu);
3310 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3311 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3312 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3314 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
3316 KsTsdu->StartOffset += KsTsduDat->TotalLength;
3318 } else if (TSDU_TYPE_BUF == KsTsduBuf->TsduType) {
3320 ASSERT(KsTsduBuf->UserBuffer != NULL);
3322 if (KsTsduBuf->DataLength > KsTsduBuf->StartOffset) {
3323 ExFreePool(KsTsduBuf->UserBuffer);
3325 cfs_enter_debugger();
3328 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
3330 } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
3333 // MDL Tsdu Unit ...
3336 TdiReturnChainedReceives(
3337 &(KsTsduMdl->Descriptor),
3340 KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
3345 return STATUS_SUCCESS;
3351 * Clean up the TsduMgrs of the KsChain
3354 * KsChain: the chain managing TsduMgr
3357 * NTSTATUS: nt status code
3370 LASSERT(NULL != KsChain);
3372 Status = KsCleanupTsduMgr(
3376 if (!NT_SUCCESS(Status)) {
3377 cfs_enter_debugger();
3381 Status = KsCleanupTsduMgr(
3382 &(KsChain->Expedited)
3385 if (!NT_SUCCESS(Status)) {
3386 cfs_enter_debugger();
3398 * Clean up all the Tsdus of a tdi connected object
3401 * tconn: the tdi connection which is connected already.
3412 ksock_tconn_t * tconn
3415 NTSTATUS Status = STATUS_SUCCESS;
3418 if (tconn->kstc_type != kstt_sender &&
3419 tconn->kstc_type != kstt_child ) {
3424 if (tconn->kstc_type == kstt_sender) {
3426 Status = KsCleanupKsChain(
3427 &(tconn->sender.kstc_recv)
3430 if (!NT_SUCCESS(Status)) {
3431 cfs_enter_debugger();
3435 Status = KsCleanupKsChain(
3436 &(tconn->sender.kstc_send)
3439 if (!NT_SUCCESS(Status)) {
3440 cfs_enter_debugger();
3446 Status = KsCleanupKsChain(
3447 &(tconn->child.kstc_recv)
3450 if (!NT_SUCCESS(Status)) {
3451 cfs_enter_debugger();
3455 Status = KsCleanupKsChain(
3456 &(tconn->child.kstc_send)
3459 if (!NT_SUCCESS(Status)) {
3460 cfs_enter_debugger();
3473 * KsCopyMdlChainToMdlChain
3474 * Copy data from a [chained] Mdl to anther [chained] Mdl.
3475 * Tdi library does not provide this function. We have to
3476 * realize it ourselives.
3479 * SourceMdlChain: the source mdl
3480 * SourceOffset: start offset of the source
3481 * DestinationMdlChain: the dst mdl
3482 * DestinationOffset: the offset where data are to be copied.
3483 * BytesTobecopied: the expteced bytes to be copied
3484 * BytesCopied: to store the really copied data length
3487 * NTSTATUS: STATUS_SUCCESS or other error code
3490 * The length of source mdl must be >= SourceOffset + BytesTobecopied
3494 KsCopyMdlChainToMdlChain(
3495 IN PMDL SourceMdlChain,
3496 IN ULONG SourceOffset,
3497 IN PMDL DestinationMdlChain,
3498 IN ULONG DestinationOffset,
3499 IN ULONG BytesTobecopied,
3500 OUT PULONG BytesCopied
3503 PMDL SrcMdl = SourceMdlChain;
3504 PMDL DstMdl = DestinationMdlChain;
3506 PUCHAR SrcBuf = NULL;
3507 PUCHAR DstBuf = NULL;
3511 NTSTATUS Status = STATUS_SUCCESS;
3514 while (dwBytes < BytesTobecopied) {
3518 while (MmGetMdlByteCount(SrcMdl) <= SourceOffset) {
3520 SourceOffset -= MmGetMdlByteCount(SrcMdl);
3522 SrcMdl = SrcMdl->Next;
3524 if (NULL == SrcMdl) {
3526 Status = STATUS_INVALID_PARAMETER;
3531 while (MmGetMdlByteCount(DstMdl) <= DestinationOffset) {
3533 DestinationOffset -= MmGetMdlByteCount(DstMdl);
3535 DstMdl = DstMdl->Next;
3537 if (NULL == DstMdl) {
3539 Status = STATUS_INVALID_PARAMETER;
3544 DstBuf = (PUCHAR)KsMapMdlBuffer(DstMdl);
3546 if ((NULL == DstBuf)) {
3547 Status = STATUS_INSUFFICIENT_RESOURCES;
3552 // Here we need skip the OVERFLOW case via RtlCopyMemory :-(
3555 if ( KsQueryMdlsSize(SrcMdl) - SourceOffset >
3556 MmGetMdlByteCount(DstMdl) - DestinationOffset ) {
3558 Length = BytesTobecopied - dwBytes;
3560 if (Length > KsQueryMdlsSize(SrcMdl) - SourceOffset) {
3561 Length = KsQueryMdlsSize(SrcMdl) - SourceOffset;
3564 if (Length > MmGetMdlByteCount(DstMdl) - DestinationOffset) {
3565 Length = MmGetMdlByteCount(DstMdl) - DestinationOffset;
3568 SrcBuf = (PUCHAR)KsMapMdlBuffer(SrcMdl);
3570 if ((NULL == DstBuf)) {
3571 Status = STATUS_INSUFFICIENT_RESOURCES;
3576 DstBuf + DestinationOffset,
3577 SrcBuf + SourceOffset,
3583 Status = TdiCopyMdlToBuffer(
3588 MmGetMdlByteCount(DstMdl),
3592 if (STATUS_BUFFER_OVERFLOW == Status) {
3593 cfs_enter_debugger();
3594 } else if (!NT_SUCCESS(Status)) {
3595 cfs_enter_debugger();
3600 SourceOffset += Length;
3601 DestinationOffset += Length;
3607 if (NT_SUCCESS(Status)) {
3608 *BytesCopied = dwBytes;
3620 * Query the whole size of a MDL (may be chained)
3623 * Mdl: the Mdl to be queried
3626 * ULONG: the total size of the mdl
3633 KsQueryMdlsSize (PMDL Mdl)
3640 // Walking the MDL Chain ...
3644 Length += MmGetMdlByteCount(Next);
3654 * Allocate MDL for the buffer and lock the pages into
3658 * UserBuffer: the user buffer to be locked
3659 * Length: length in bytes of the buffer
3660 * Operation: read or write access
3661 * pMdl: the result of the created mdl
3664 * NTSTATUS: kernel status code (STATUS_SUCCESS
3665 * or other error code)
3673 IN PVOID UserBuffer,
3676 IN LOCK_OPERATION Operation,
3683 LASSERT(UserBuffer != NULL);
3687 Mdl = IoAllocateMdl(
3697 Status = STATUS_INSUFFICIENT_RESOURCES;
3704 MmProbeAndLockPages(
3710 MmBuildMdlForNonPagedPool(
3715 Status = STATUS_SUCCESS;
3719 } __except (EXCEPTION_EXECUTE_HANDLER) {
3725 cfs_enter_debugger();
3727 Status = STATUS_INVALID_USER_BUFFER;
3736 * Map the mdl into a buffer in kernel space
3739 * Mdl: the mdl to be mapped
3742 * PVOID: the buffer mapped or NULL in failure
3749 KsMapMdlBuffer (PMDL Mdl)
3751 LASSERT(Mdl != NULL);
3753 return MmGetSystemAddressForMdlSafe(
3762 * Unlock all the pages in the mdl
3765 * Mdl: memory description list to be released
3775 KsReleaseMdl (IN PMDL Mdl,
3778 LASSERT(Mdl != NULL);
3799 * allocate MDL for the user spepcified buffer and lock (paging-in)
3800 * all the pages of the buffer into system memory
3803 * buffer: the user buffer to be locked
3804 * length: length in bytes of the buffer
3805 * access: read or write access
3806 * mdl: the result of the created mdl
3809 * int: the ks error code: 0: success / -x: failture
3820 LOCK_OPERATION access,
3826 status = KsLockUserBuffer(
3834 return cfs_error_code(status);
3840 * Map the mdl pages into kernel space
3843 * mdl: the mdl to be mapped
3846 * void *: the buffer mapped or NULL in failure
3853 ks_map_mdl (ksock_mdl_t * mdl)
3855 LASSERT(mdl != NULL);
3857 return KsMapMdlBuffer(mdl);
3862 * Unlock all the pages in the mdl and release the mdl
3865 * mdl: memory description list to be released
3875 ks_release_mdl (ksock_mdl_t *mdl, int paged)
3877 LASSERT(mdl != NULL);
3879 KsReleaseMdl(mdl, paged);
3885 * allocate a new tconn structure from the SLAB cache or
3886 * NonPaged sysetm pool
3892 * ksock_tconn_t *: the address of tconn or NULL if it fails
3901 ksock_tconn_t * tconn = NULL;
3903 /* allocate ksoc_tconn_t from the slab cache memory */
3905 tconn = (ksock_tconn_t *)cfs_mem_cache_alloc(
3906 ks_data.ksnd_tconn_slab, CFS_ALLOC_ZERO);
3910 /* zero tconn elements */
3911 memset(tconn, 0, sizeof(ksock_tconn_t));
3913 /* initialize the tconn ... */
3914 tconn->kstc_magic = KS_TCONN_MAGIC;
3916 ExInitializeWorkItem(
3917 &(tconn->kstc_disconnect.WorkItem),
3919 &(tconn->kstc_disconnect)
3923 &(tconn->kstc_disconnect.Event),
3924 SynchronizationEvent,
3927 ExInitializeWorkItem(
3928 &(tconn->kstc_destroy),
3933 spin_lock_init(&(tconn->kstc_lock));
3935 ks_get_tconn(tconn);
3937 spin_lock(&(ks_data.ksnd_tconn_lock));
3939 /* attach it into global list in ks_data */
3941 list_add(&(tconn->kstc_list), &(ks_data.ksnd_tconns));
3942 ks_data.ksnd_ntconns++;
3943 spin_unlock(&(ks_data.ksnd_tconn_lock));
3945 tconn->kstc_rcv_wnd = tconn->kstc_snd_wnd = 0x10000;
3954 * free the tconn structure to the SLAB cache or NonPaged
3958 * tconn: the tcon is to be freed
3968 ks_free_tconn(ksock_tconn_t * tconn)
3970 LASSERT(atomic_read(&(tconn->kstc_refcount)) == 0);
3972 spin_lock(&(ks_data.ksnd_tconn_lock));
3974 /* remove it from the global list */
3975 list_del(&tconn->kstc_list);
3976 ks_data.ksnd_ntconns--;
3978 /* if this is the last tconn, it would be safe for
3979 ks_tdi_fini_data to quit ... */
3980 if (ks_data.ksnd_ntconns == 0) {
3981 cfs_wake_event(&ks_data.ksnd_tconn_exit);
3983 spin_unlock(&(ks_data.ksnd_tconn_lock));
3985 /* free the structure memory */
3986 cfs_mem_cache_free(ks_data.ksnd_tconn_slab, tconn);
3992 * Initialize the tconn as a listener (daemon)
3995 * tconn: the listener tconn
4006 ksock_tconn_t * tconn
4009 /* preparation: intialize the tconn members */
4011 tconn->kstc_type = kstt_listener;
4013 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4015 CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_listening.list));
4016 CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_accepted.list));
4018 cfs_init_event( &(tconn->listener.kstc_accept_event),
4022 cfs_init_event( &(tconn->listener.kstc_destroy_event),
4026 tconn->kstc_state = ksts_inited;
4032 * Initialize the tconn as a sender
4035 * tconn: the sender tconn
4046 ksock_tconn_t * tconn
4049 tconn->kstc_type = kstt_sender;
4050 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4052 KsInitializeKsChain(&(tconn->sender.kstc_recv));
4053 KsInitializeKsChain(&(tconn->sender.kstc_send));
4055 tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4056 tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4058 tconn->kstc_state = ksts_inited;
4063 * Initialize the tconn as a child
4066 * tconn: the child tconn
4077 ksock_tconn_t * tconn
4080 tconn->kstc_type = kstt_child;
4081 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4083 KsInitializeKsChain(&(tconn->child.kstc_recv));
4084 KsInitializeKsChain(&(tconn->child.kstc_send));
4086 tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4087 tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4089 tconn->kstc_state = ksts_inited;
4094 * increase the reference count of the tconn with 1
4097 * tconn: the tdi connection to be referred
4108 ksock_tconn_t * tconn
4111 atomic_inc(&(tconn->kstc_refcount));
4116 * decrease the reference count of the tconn and destroy
4117 * it if the refercount becomes 0.
4120 * tconn: the tdi connection to be dereferred
4131 ksock_tconn_t *tconn
4134 if (atomic_dec_and_test(&(tconn->kstc_refcount))) {
4136 spin_lock(&(tconn->kstc_lock));
4138 if ( ( tconn->kstc_type == kstt_child ||
4139 tconn->kstc_type == kstt_sender ) &&
4140 ( tconn->kstc_state == ksts_connected ) ) {
4142 spin_unlock(&(tconn->kstc_lock));
4144 ks_abort_tconn(tconn);
4148 if (cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY)) {
4149 cfs_enter_debugger();
4152 &(tconn->kstc_destroy),
4156 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY);
4159 spin_unlock(&(tconn->kstc_lock));
4166 * cleanup the tdi connection and free it
4169 * tconn: the tdi connection to be cleaned.
4180 ksock_tconn_t * tconn
4183 LASSERT(tconn->kstc_refcount.counter == 0);
4185 if (tconn->kstc_type == kstt_listener) {
4187 ks_reset_handlers(tconn);
4189 /* for listener, we just need to close the address object */
4191 tconn->kstc_addr.Handle,
4192 tconn->kstc_addr.FileObject
4195 tconn->kstc_state = ksts_inited;
4197 } else if (tconn->kstc_type == kstt_child) {
4199 /* for child tdi conections */
4201 /* disassociate the relation between it's connection object
4202 and the address object */
4204 if (tconn->kstc_state == ksts_associated) {
4205 KsDisassociateAddress(
4206 tconn->child.kstc_info.FileObject
4210 /* release the connection object */
4213 tconn->child.kstc_info.Handle,
4214 tconn->child.kstc_info.FileObject
4217 /* release it's refer of it's parent's address object */
4220 tconn->kstc_addr.FileObject
4223 spin_lock(&tconn->child.kstc_parent->kstc_lock);
4224 spin_lock(&tconn->kstc_lock);
4226 tconn->kstc_state = ksts_inited;
4228 /* remove it frome it's parent's queues */
4230 if (tconn->child.kstc_queued) {
4232 list_del(&(tconn->child.kstc_link));
4234 if (tconn->child.kstc_queueno) {
4236 LASSERT(tconn->child.kstc_parent->listener.kstc_accepted.num > 0);
4237 tconn->child.kstc_parent->listener.kstc_accepted.num -= 1;
4241 LASSERT(tconn->child.kstc_parent->listener.kstc_listening.num > 0);
4242 tconn->child.kstc_parent->listener.kstc_listening.num -= 1;
4245 tconn->child.kstc_queued = FALSE;
4248 spin_unlock(&tconn->kstc_lock);
4249 spin_unlock(&tconn->child.kstc_parent->kstc_lock);
4251 /* drop the reference of the parent tconn */
4252 ks_put_tconn(tconn->child.kstc_parent);
4254 } else if (tconn->kstc_type == kstt_sender) {
4256 ks_reset_handlers(tconn);
4258 /* release the connection object */
4261 tconn->sender.kstc_info.Handle,
4262 tconn->sender.kstc_info.FileObject
4265 /* release it's refer of it's parent's address object */
4267 tconn->kstc_addr.Handle,
4268 tconn->kstc_addr.FileObject
4271 tconn->kstc_state = ksts_inited;
4274 cfs_enter_debugger();
4277 /* free the tconn structure ... */
4279 ks_free_tconn(tconn);
4284 ksock_tconn_t * tconn,
4291 PKS_TSDUMGR KsTsduMgr;
4295 ks_get_tconn(tconn);
4296 spin_lock(&(tconn->kstc_lock));
4298 if ( tconn->kstc_type != kstt_sender &&
4299 tconn->kstc_type != kstt_child) {
4301 spin_unlock(&(tconn->kstc_lock));
4305 if (tconn->kstc_state != ksts_connected) {
4307 spin_unlock(&(tconn->kstc_lock));
4311 if (tconn->kstc_type == kstt_sender) {
4312 KsChain = &(tconn->sender.kstc_recv);
4314 LASSERT(tconn->kstc_type == kstt_child);
4315 KsChain = &(tconn->child.kstc_recv);
4319 KsTsduMgr = &(KsChain->Expedited);
4321 KsTsduMgr = &(KsChain->Normal);
4324 *size = KsTsduMgr->TotalBytes;
4325 spin_unlock(&(tconn->kstc_lock));
4329 ks_put_tconn(tconn);
4336 * Query the the options of the tcp stream connnection
4339 * tconn: the tdi connection
4341 * OptionValue: buffer to store the option value
4342 * Length: the length of the value, to be returned
4345 * int: ks return code
4353 ksock_tconn_t * tconn,
4359 NTSTATUS Status = STATUS_SUCCESS;
4361 IO_STATUS_BLOCK IoStatus;
4363 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfoEx;
4365 PFILE_OBJECT ConnectionObject;
4366 PDEVICE_OBJECT DeviceObject = NULL;
4369 PIO_STACK_LOCATION IrpSp = NULL;
4373 /* make sure the tdi connection is connected ? */
4375 ks_get_tconn(tconn);
4377 if (tconn->kstc_state != ksts_connected) {
4378 Status = STATUS_INVALID_PARAMETER;
4382 LASSERT(tconn->kstc_type == kstt_sender ||
4383 tconn->kstc_type == kstt_child);
4385 if (tconn->kstc_type == kstt_sender) {
4386 ConnectionObject = tconn->sender.kstc_info.FileObject;
4388 ConnectionObject = tconn->child.kstc_info.FileObject;
4391 QueryInfoEx.ID.toi_id = ID;
4392 QueryInfoEx.ID.toi_type = INFO_TYPE_CONNECTION;
4393 QueryInfoEx.ID.toi_class = INFO_CLASS_PROTOCOL;
4394 QueryInfoEx.ID.toi_entity.tei_entity = CO_TL_ENTITY;
4395 QueryInfoEx.ID.toi_entity.tei_instance = 0;
4397 RtlZeroMemory(&(QueryInfoEx.Context), CONTEXT_SIZE);
4399 KeInitializeEvent(&Event, NotificationEvent, FALSE);
4400 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4402 Irp = IoBuildDeviceIoControlRequest(
4403 IOCTL_TCP_QUERY_INFORMATION_EX,
4406 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
4415 Status = STATUS_INSUFFICIENT_RESOURCES;
4419 IrpSp = IoGetNextIrpStackLocation(Irp);
4421 if (IrpSp == NULL) {
4425 Status = STATUS_INSUFFICIENT_RESOURCES;
4429 IrpSp->FileObject = ConnectionObject;
4430 IrpSp->DeviceObject = DeviceObject;
4432 Status = IoCallDriver(DeviceObject, Irp);
4434 if (Status == STATUS_PENDING) {
4436 KeWaitForSingleObject(
4444 Status = IoStatus.Status;
4448 if (NT_SUCCESS(Status)) {
4449 *Length = IoStatus.Information;
4451 cfs_enter_debugger();
4452 memset(OptionValue, 0, *Length);
4453 Status = STATUS_SUCCESS;
4458 ks_put_tconn(tconn);
4460 return cfs_error_code(Status);
4465 * Set the the options for the tcp stream connnection
4468 * tconn: the tdi connection
4470 * OptionValue: buffer containing the new option value
4471 * Length: the length of the value
4474 * int: ks return code
4482 ksock_tconn_t * tconn,
4488 NTSTATUS Status = STATUS_SUCCESS;
4490 IO_STATUS_BLOCK IoStatus;
4492 ULONG SetInfoExLength;
4493 PTCP_REQUEST_SET_INFORMATION_EX SetInfoEx = NULL;
4495 PFILE_OBJECT ConnectionObject;
4496 PDEVICE_OBJECT DeviceObject = NULL;
4499 PIO_STACK_LOCATION IrpSp = NULL;
4503 /* make sure the tdi connection is connected ? */
4505 ks_get_tconn(tconn);
4507 if (tconn->kstc_state != ksts_connected) {
4508 Status = STATUS_INVALID_PARAMETER;
4512 LASSERT(tconn->kstc_type == kstt_sender ||
4513 tconn->kstc_type == kstt_child);
4515 if (tconn->kstc_type == kstt_sender) {
4516 ConnectionObject = tconn->sender.kstc_info.FileObject;
4518 ConnectionObject = tconn->child.kstc_info.FileObject;
4521 SetInfoExLength = sizeof(TCP_REQUEST_SET_INFORMATION_EX) - 1 + Length + sizeof(KEVENT);
4523 SetInfoEx = ExAllocatePoolWithTag(
4529 if (SetInfoEx == NULL) {
4530 Status = STATUS_INSUFFICIENT_RESOURCES;
4534 SetInfoEx->ID.toi_id = ID;
4536 SetInfoEx->ID.toi_type = INFO_TYPE_CONNECTION;
4537 SetInfoEx->ID.toi_class = INFO_CLASS_PROTOCOL;
4538 SetInfoEx->ID.toi_entity.tei_entity = CO_TL_ENTITY;
4539 SetInfoEx->ID.toi_entity.tei_instance = TL_INSTANCE;
4541 SetInfoEx->BufferSize = Length;
4542 RtlCopyMemory(&(SetInfoEx->Buffer[0]), OptionValue, Length);
4544 Event = (PKEVENT)(&(SetInfoEx->Buffer[Length]));
4545 KeInitializeEvent(Event, NotificationEvent, FALSE);
4547 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4549 Irp = IoBuildDeviceIoControlRequest(
4550 IOCTL_TCP_SET_INFORMATION_EX,
4562 Status = STATUS_INSUFFICIENT_RESOURCES;
4566 IrpSp = IoGetNextIrpStackLocation(Irp);
4568 if (IrpSp == NULL) {
4571 Status = STATUS_INSUFFICIENT_RESOURCES;
4575 IrpSp->FileObject = ConnectionObject;
4576 IrpSp->DeviceObject = DeviceObject;
4578 Status = IoCallDriver(DeviceObject, Irp);
4580 if (Status == STATUS_PENDING) {
4582 KeWaitForSingleObject(
4590 Status = IoStatus.Status;
4596 ExFreePool(SetInfoEx);
4599 if (!NT_SUCCESS(Status)) {
4600 printk("ks_set_tcp_option: error setup tcp option: ID (%d), Status = %xh\n",
4602 Status = STATUS_SUCCESS;
4605 ks_put_tconn(tconn);
4607 return cfs_error_code(Status);
4612 * bind the tdi connection object with an address
4615 * tconn: tconn to be bound
4616 * parent: the parent tconn object
4617 * ipaddr: the ip address
4618 * port: the port number
4621 * int: 0 for success or ks error codes.
4629 ksock_tconn_t * tconn,
4630 ksock_tconn_t * parent,
4638 ksock_tdi_addr_t taddr;
4640 memset(&taddr, 0, sizeof(ksock_tdi_addr_t));
4642 if (tconn->kstc_state != ksts_inited) {
4644 status = STATUS_INVALID_PARAMETER;
4645 rc = cfs_error_code(status);
4649 } else if (tconn->kstc_type == kstt_child) {
4651 if (NULL == parent) {
4652 status = STATUS_INVALID_PARAMETER;
4653 rc = cfs_error_code(status);
4658 /* refer it's parent's address object */
4660 taddr = parent->kstc_addr;
4661 ObReferenceObject(taddr.FileObject);
4663 ks_get_tconn(parent);
4667 PTRANSPORT_ADDRESS TdiAddress = &(taddr.Tdi);
4670 /* intialize the tdi address*/
4672 TdiAddress->TAAddressCount = 1;
4673 TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
4674 TdiAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
4676 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
4677 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
4679 memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
4682 /* open the transport address object */
4684 AddrLen = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) +
4685 TDI_ADDRESS_LENGTH_IP;
4687 status = KsOpenAddress(
4695 if (!NT_SUCCESS(status)) {
4697 KsPrint((0, "ks_bind_tconn: failed to open ip addr object (%x:%d), status = %xh\n",
4698 addr, port, status ));
4699 rc = cfs_error_code(status);
4704 if (tconn->kstc_type == kstt_child) {
4705 tconn->child.kstc_parent = parent;
4708 tconn->kstc_state = ksts_bind;
4709 tconn->kstc_addr = taddr;
4718 * build tcp/streaming connection to remote peer
4721 * tconn: tconn to be connected to the peer
4722 * addr: the peer's ip address
4723 * port: the peer's port number
4726 * int: 0 for success or ks error codes.
4734 ksock_tconn_t * tconn,
4740 NTSTATUS status = STATUS_SUCCESS;
4743 PFILE_OBJECT ConnectionObject = NULL;
4744 PDEVICE_OBJECT DeviceObject = NULL;
4746 PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
4751 LASSERT(tconn->kstc_type == kstt_sender);
4752 LASSERT(tconn->kstc_state == ksts_bind);
4754 ks_get_tconn(tconn);
4757 /* set the event callbacks */
4758 rc = ks_set_handlers(tconn);
4761 cfs_enter_debugger();
4766 /* create the connection file handle / object */
4767 status = KsOpenConnection(
4769 (CONNECTION_CONTEXT)tconn,
4770 &(tconn->sender.kstc_info.Handle),
4771 &(tconn->sender.kstc_info.FileObject)
4774 if (!NT_SUCCESS(status)) {
4775 rc = cfs_error_code(status);
4776 cfs_enter_debugger();
4780 /* associdate the the connection with the adress object of the tconn */
4782 status = KsAssociateAddress(
4783 tconn->kstc_addr.Handle,
4784 tconn->sender.kstc_info.FileObject
4787 if (!NT_SUCCESS(status)) {
4788 rc = cfs_error_code(status);
4789 cfs_enter_debugger();
4793 tconn->kstc_state = ksts_associated;
4795 /* Allocating Connection Info Together with the Address */
4796 AddrLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
4797 + TDI_ADDRESS_LENGTH_IP;
4799 ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
4800 NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + AddrLength, 'iCsK');
4802 if (NULL == ConnectionInfo) {
4804 status = STATUS_INSUFFICIENT_RESOURCES;
4805 rc = cfs_error_code(status);
4806 cfs_enter_debugger();
4810 /* Initializing ConnectionInfo ... */
4812 PTRANSPORT_ADDRESS TdiAddress;
4814 /* ConnectionInfo settings */
4816 ConnectionInfo->UserDataLength = 0;
4817 ConnectionInfo->UserData = NULL;
4818 ConnectionInfo->OptionsLength = 0;
4819 ConnectionInfo->Options = NULL;
4820 ConnectionInfo->RemoteAddressLength = AddrLength;
4821 ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
4824 /* intialize the tdi address*/
4826 TdiAddress = ConnectionInfo->RemoteAddress;
4828 TdiAddress->TAAddressCount = 1;
4829 TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
4830 TdiAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
4832 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
4833 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
4835 memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
4838 /* Now prepare to connect the remote peer ... */
4840 ConnectionObject = tconn->sender.kstc_info.FileObject;
4841 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4843 /* allocate a new Irp */
4845 Irp = KsBuildTdiIrp(DeviceObject);
4849 status = STATUS_INSUFFICIENT_RESOURCES;
4850 rc = cfs_error_code(status);
4851 cfs_enter_debugger();
4869 /* sumbit the Irp to the underlying transport driver */
4870 status = KsSubmitTdiIrp(
4877 spin_lock(&(tconn->kstc_lock));
4879 if (NT_SUCCESS(status)) {
4881 /* Connected! the conneciton is built successfully. */
4883 tconn->kstc_state = ksts_connected;
4885 tconn->sender.kstc_info.ConnectionInfo = ConnectionInfo;
4886 tconn->sender.kstc_info.Remote = ConnectionInfo->RemoteAddress;
4888 spin_unlock(&(tconn->kstc_lock));
4892 /* Not connected! Abort it ... */
4895 cfs_enter_debugger();
4899 rc = cfs_error_code(status);
4901 tconn->kstc_state = ksts_associated;
4902 spin_unlock(&(tconn->kstc_lock));
4904 /* disassocidate the connection and the address object,
4905 after cleanup, it's safe to set the state to abort ... */
4907 if ( NT_SUCCESS(KsDisassociateAddress(
4908 tconn->sender.kstc_info.FileObject))) {
4909 tconn->kstc_state = ksts_aborted;
4912 /* reset the event callbacks */
4913 rc = ks_reset_handlers(tconn);
4920 if (NT_SUCCESS(status)) {
4922 ks_query_local_ipaddr(tconn);
4926 if (ConnectionInfo) {
4927 ExFreePool(ConnectionInfo);
4934 ks_put_tconn(tconn);
4941 * ks_disconnect_tconn
4942 * disconnect the tconn from a connection
4945 * tconn: the tdi connecton object connected already
4946 * flags: flags & options for disconnecting
4949 * int: ks error code
4956 ks_disconnect_tconn(
4957 ksock_tconn_t * tconn,
4961 NTSTATUS status = STATUS_SUCCESS;
4963 ksock_tconn_info_t * info;
4965 PFILE_OBJECT ConnectionObject;
4966 PDEVICE_OBJECT DeviceObject = NULL;
4972 ks_get_tconn(tconn);
4974 /* make sure tt's connected already and it
4975 must be a sender or a child ... */
4977 LASSERT(tconn->kstc_state == ksts_connected);
4978 LASSERT( tconn->kstc_type == kstt_sender ||
4979 tconn->kstc_type == kstt_child);
4981 /* reset all the event handlers to NULL */
4983 if (tconn->kstc_type != kstt_child) {
4984 ks_reset_handlers (tconn);
4987 /* Disconnecting to the remote peer ... */
4989 if (tconn->kstc_type == kstt_sender) {
4990 info = &(tconn->sender.kstc_info);
4992 info = &(tconn->child.kstc_info);
4995 ConnectionObject = info->FileObject;
4996 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4998 /* allocate an Irp and setup it */
5000 Irp = KsBuildTdiIrp(DeviceObject);
5004 status = STATUS_INSUFFICIENT_RESOURCES;
5005 cfs_enter_debugger();
5011 SynchronizationEvent,
5019 KsDisconectCompletionRoutine,
5027 /* issue the Irp to the underlying transport
5028 driver to disconnect the connection */
5030 status = IoCallDriver(DeviceObject, Irp);
5032 if (STATUS_PENDING == status) {
5034 status = KeWaitForSingleObject(
5042 status = Irp->IoStatus.Status;
5045 KsPrint((2, "KsDisconnect: Disconnection is done with Status = %xh (%s) ...\n",
5046 status, KsNtStatusToString(status)));
5050 if (info->ConnectionInfo) {
5052 /* disassociate the association between connection/address objects */
5054 status = KsDisassociateAddress(ConnectionObject);
5056 if (!NT_SUCCESS(status)) {
5057 cfs_enter_debugger();
5060 spin_lock(&(tconn->kstc_lock));
5062 /* cleanup the tsdumgr Lists */
5063 KsCleanupTsdu (tconn);
5065 /* set the state of the tconn */
5066 if (NT_SUCCESS(status)) {
5067 tconn->kstc_state = ksts_disconnected;
5069 tconn->kstc_state = ksts_associated;
5072 /* free the connection info to system pool*/
5073 ExFreePool(info->ConnectionInfo);
5074 info->ConnectionInfo = NULL;
5075 info->Remote = NULL;
5077 spin_unlock(&(tconn->kstc_lock));
5080 status = STATUS_SUCCESS;
5084 ks_put_tconn(tconn);
5086 return cfs_error_code(status);
5092 * The connection is broken un-expectedly. We need do
5096 * tconn: the tdi connection
5107 ksock_tconn_t * tconn
5110 PKS_DISCONNECT_WORKITEM WorkItem = NULL;
5112 WorkItem = &(tconn->kstc_disconnect);
5114 ks_get_tconn(tconn);
5115 spin_lock(&(tconn->kstc_lock));
5117 if (tconn->kstc_state != ksts_connected) {
5118 ks_put_tconn(tconn);
5121 if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
5123 WorkItem->Flags = TDI_DISCONNECT_ABORT;
5124 WorkItem->tconn = tconn;
5126 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
5129 &(WorkItem->WorkItem),
5135 spin_unlock(&(tconn->kstc_lock));
5140 * ks_query_local_ipaddr
5141 * query the local connection ip address
5144 * tconn: the tconn which is connected
5147 * int: ks error code
5154 ks_query_local_ipaddr(
5155 ksock_tconn_t * tconn
5158 PFILE_OBJECT FileObject = NULL;
5161 PTRANSPORT_ADDRESS TdiAddress;
5162 ULONG AddressLength;
5164 if (tconn->kstc_type == kstt_sender) {
5165 FileObject = tconn->sender.kstc_info.FileObject;
5166 } else if (tconn->kstc_type == kstt_child) {
5167 FileObject = tconn->child.kstc_info.FileObject;
5169 status = STATUS_INVALID_PARAMETER;
5173 TdiAddress = &(tconn->kstc_addr.Tdi);
5174 AddressLength = MAX_ADDRESS_LENGTH;
5176 status = KsQueryIpAddress(FileObject, TdiAddress, &AddressLength);
5178 if (NT_SUCCESS(status)) {
5180 KsPrint((0, "ks_query_local_ipaddr: Local ip address = %xh port = %xh\n",
5181 ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->in_addr,
5182 ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->sin_port ));
5184 KsPrint((0, "KsQueryonnectionIpAddress: Failed to query the connection local ip address.\n"));
5189 return cfs_error_code(status);
5194 * send MDL chain to the peer for a stream connection
5197 * tconn: tdi connection object
5198 * tx: the transmit context
5199 * mdl: the mdl chain containing the data
5200 * len: length of the data
5201 * flags: flags of the transmission
5212 ksock_tconn_t * tconn,
5223 ksock_tdi_tx_t * context;
5226 PKS_TSDUMGR KsTsduMgr;
5228 PKS_TSDU_BUF KsTsduBuf;
5229 PKS_TSDU_DAT KsTsduDat;
5231 BOOLEAN bNewTsdu = FALSE; /* newly allocated */
5232 BOOLEAN bNewBuff = FALSE; /* newly allocated */
5234 BOOLEAN bBuffed; /* bufferred sending */
5236 PUCHAR Buffer = NULL;
5237 ksock_mdl_t * NewMdl = NULL;
5240 PFILE_OBJECT ConnObject;
5241 PDEVICE_OBJECT DeviceObject;
5243 BOOLEAN bIsNonBlock;
5245 ks_get_tconn(tconn);
5247 tflags = ks_tdi_send_flags(flags);
5248 bIsNonBlock = cfs_is_flag_set(flags, MSG_DONTWAIT);
5250 spin_lock(&tconn->kstc_lock);
5252 LASSERT( tconn->kstc_type == kstt_sender ||
5253 tconn->kstc_type == kstt_child );
5255 if (tconn->kstc_state != ksts_connected) {
5256 spin_unlock(&tconn->kstc_lock);
5257 ks_put_tconn(tconn);
5261 /* get the latest Tsdu buffer form TsduMgr list.
5262 just set NULL if the list is empty. */
5264 if (tconn->kstc_type == kstt_sender) {
5265 KsChain = &(tconn->sender.kstc_send);
5267 LASSERT(tconn->kstc_type == kstt_child);
5268 KsChain = &(tconn->child.kstc_send);
5271 if (cfs_is_flag_set(tflags, TDI_SEND_EXPEDITED)) {
5272 KsTsduMgr = &(KsChain->Expedited);
5274 KsTsduMgr = &(KsChain->Normal);
5277 if (KsTsduMgr->TotalBytes + len <= tconn->kstc_snd_wnd) {
5283 /* do the preparation work for bufferred sending */
5287 /* if the data is even larger than the biggest Tsdu, we have
5288 to allocate new buffer and use TSDU_TYOE_BUF to store it */
5290 if ( KS_TSDU_STRU_SIZE((ULONG)len) > ks_data.ksnd_tsdu_size
5291 - KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
5295 if (list_empty(&(KsTsduMgr->TsduList))) {
5297 LASSERT(KsTsduMgr->NumOfTsdu == 0);
5302 LASSERT(KsTsduMgr->NumOfTsdu > 0);
5303 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
5304 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
5307 /* check whether KsTsdu free space is enough, or we need alloc new Tsdu */
5309 if (sizeof(KS_TSDU_BUF) + KsTsdu->LastOffset > KsTsdu->TotalLength) {
5313 if ( KS_TSDU_STRU_SIZE((ULONG)len) >
5314 KsTsdu->TotalLength - KsTsdu->LastOffset ) {
5320 /* if there's no Tsdu or the free size is not enough for the
5321 KS_TSDU_BUF or KS_TSDU_DAT. We need re-allocate a new Tsdu. */
5323 if (NULL == KsTsdu) {
5325 KsTsdu = KsAllocateKsTsdu();
5327 if (NULL == KsTsdu) {
5335 /* process the case that a new buffer is to be allocated from system memory */
5338 /* now allocating internal buffer to contain the payload */
5339 Buffer = ExAllocatePool(NonPagedPool, len);
5341 if (NULL == Buffer) {
5351 /* queue a new KS_TSDU_BUF to the Tsdu buffer */
5352 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
5354 KsTsduBuf->TsduFlags = 0;
5355 KsTsduBuf->DataLength = (ULONG)len;
5356 KsTsduBuf->StartOffset = 0;
5357 KsTsduBuf->UserBuffer = Buffer;
5359 /* queue a new KS_TSDU_BUF to the Tsdu buffer */
5360 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
5362 KsTsduDat->TsduFlags = 0;
5363 KsTsduDat->DataLength = (ULONG)len;
5364 KsTsduDat->StartOffset = 0;
5365 KsTsduDat->TotalLength = KS_TSDU_STRU_SIZE((ULONG)len);
5367 Buffer = &KsTsduDat->Data[0];
5370 /* now locking the Buffer and copy user payload into the buffer */
5371 ASSERT(Buffer != NULL);
5373 rc = ks_lock_buffer(Buffer, FALSE, len, IoReadAccess, &NewMdl);
5375 printk("ks_send_mdl: bufferred: error allocating mdl.\n");
5378 ULONG BytesCopied = 0;
5379 TdiCopyMdlToBuffer(mdl, 0, Buffer, 0, (ULONG)len, &BytesCopied);
5380 if (BytesCopied != (ULONG) len) {
5385 /* Do the finializing job if we succeed to to lock the buffer and move
5386 user data. Or we need do cleaning up ... */
5390 KsTsduBuf->TsduType = TSDU_TYPE_BUF;
5391 KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
5394 KsTsduDat->TsduType = TSDU_TYPE_DAT;
5395 KsTsdu->LastOffset += KsTsduDat->TotalLength;
5398 /* attach it to the TsduMgr list if the Tsdu is newly created. */
5401 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
5402 KsTsduMgr->NumOfTsdu++;
5408 ks_release_mdl(NewMdl, FALSE);
5420 /* update the TotalBytes being in sending */
5421 KsTsduMgr->TotalBytes += (ULONG)len;
5423 spin_unlock(&tconn->kstc_lock);
5425 /* cleanup the Tsdu if not successful */
5426 if (!bBuffed && bNewTsdu) {
5427 KsPutKsTsdu(KsTsdu);
5432 /* we need allocate the ksock_tx_t structure from memory pool. */
5434 context = cfs_alloc(sizeof(ksock_tdi_tx_t) + sizeof(KEVENT),0);
5436 /* release the chained mdl */
5437 ks_release_mdl(mdl, FALSE);
5439 Status = STATUS_INSUFFICIENT_RESOURCES;
5443 /* intialize the TcpContext */
5445 memset(context,0, sizeof(ksock_tdi_tx_t) + sizeof(KEVENT));
5447 context->tconn = tconn;
5448 context->Event = (PKEVENT) ((PUCHAR)context + sizeof(ksock_tdi_tx_t));
5450 KeInitializeEvent(context->Event, SynchronizationEvent, FALSE);
5454 /* for bufferred transmission, we need set
5455 the internal completion routine. */
5457 context->CompletionRoutine = KsTcpSendCompletionRoutine;
5458 context->KsTsduMgr = KsTsduMgr;
5459 context->CompletionContext = KsTsdu;
5460 context->CompletionContext2 = (bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat);
5461 context->bCounted = FALSE;
5463 } else if (bIsNonBlock) {
5465 /* for non-blocking transmission, we need set
5466 the internal completion routine too. */
5468 context->CompletionRoutine = KsTcpSendCompletionRoutine;
5469 context->CompletionContext = tx;
5470 context->KsTsduMgr = KsTsduMgr;
5471 context->bCounted = TRUE;
5472 context->ReferCount = 2;
5475 if (tconn->kstc_type == kstt_sender) {
5476 ConnObject = tconn->sender.kstc_info.FileObject;
5478 LASSERT(tconn->kstc_type == kstt_child);
5479 ConnObject = tconn->child.kstc_info.FileObject;
5482 DeviceObject = IoGetRelatedDeviceObject(ConnObject);
5484 Irp = KsBuildTdiIrp(DeviceObject);
5488 /* release the chained mdl */
5489 ks_release_mdl(mdl, FALSE);
5491 Status = STATUS_INSUFFICIENT_RESOURCES;
5495 length = KsQueryMdlsSize(mdl);
5497 LASSERT((ULONG)len <= length);
5499 ks_get_tconn(tconn);
5505 KsTcpCompletionRoutine,
5507 (bBuffed ? NewMdl : mdl),
5508 (bBuffed ? (tflags | TDI_SEND_NON_BLOCKING) : tflags),
5512 Status = IoCallDriver(DeviceObject, Irp);
5515 ks_release_mdl(mdl, FALSE);
5519 if (!NT_SUCCESS(Status)) {
5520 cfs_enter_debugger();
5521 rc = cfs_error_code(Status);
5526 Status = STATUS_SUCCESS;
5531 if (InterlockedDecrement(&context->ReferCount) == 0) {
5532 Status = Irp->IoStatus.Status;
5534 Status = STATUS_PENDING;
5538 if (STATUS_PENDING == Status) {
5539 Status = KeWaitForSingleObject(
5547 if (NT_SUCCESS(Status)) {
5548 Status = Irp->IoStatus.Status;
5553 if (Status == STATUS_SUCCESS) {
5554 rc = (int)(Irp->IoStatus.Information);
5556 spin_lock(&tconn->kstc_lock);
5557 KsTsduMgr->TotalBytes -= rc;
5558 spin_unlock(&tconn->kstc_lock);
5561 rc = cfs_error_code(Status);
5570 ks_release_mdl(NewMdl, FALSE);
5575 if (!NT_SUCCESS(Status)) {
5583 if (Status != STATUS_PENDING) {
5587 /* Freeing the Irp ... */
5595 if (!NT_SUCCESS(Status)) {
5597 spin_lock(&tconn->kstc_lock);
5599 KsTsduMgr->TotalBytes -= (ULONG)len;
5603 /* attach it to the TsduMgr list if the Tsdu is newly created. */
5606 list_del(&(KsTsdu->Link));
5607 KsTsduMgr->NumOfTsdu--;
5609 KsPutKsTsdu(KsTsdu);
5612 if ( (ulong_ptr)KsTsduBuf + sizeof(KS_TSDU_BUF) ==
5613 (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
5614 KsTsdu->LastOffset -= sizeof(KS_TSDU_BUF);
5615 KsTsduBuf->TsduType = 0;
5617 cfs_enter_debugger();
5618 KsTsduBuf->StartOffset = KsTsduBuf->DataLength;
5621 if ( (ulong_ptr)KsTsduDat + KsTsduDat->TotalLength ==
5622 (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
5623 KsTsdu->LastOffset -= KsTsduDat->TotalLength;
5624 KsTsduDat->TsduType = 0;
5626 cfs_enter_debugger();
5627 KsTsduDat->StartOffset = KsTsduDat->DataLength;
5633 spin_unlock(&tconn->kstc_lock);
5636 /* free the context if is not used at all */
5641 ks_put_tconn(tconn);
5648 * Receive data from the peer for a stream connection
5651 * tconn: tdi connection object
5652 * mdl: the mdl chain to contain the incoming data
5653 * len: length of the data
5654 * flags: flags of the receiving
5665 ksock_tconn_t * tconn,
5671 NTSTATUS Status = STATUS_SUCCESS;
5674 BOOLEAN bIsNonBlock;
5675 BOOLEAN bIsExpedited;
5678 PKS_TSDUMGR KsTsduMgr;
5680 PKS_TSDU_DAT KsTsduDat;
5681 PKS_TSDU_BUF KsTsduBuf;
5682 PKS_TSDU_MDL KsTsduMdl;
5686 ULONG BytesRecved = 0;
5689 bIsNonBlock = cfs_is_flag_set(flags, MSG_DONTWAIT);
5690 bIsExpedited = cfs_is_flag_set(flags, MSG_OOB);
5692 ks_get_tconn(tconn);
5698 spin_lock(&(tconn->kstc_lock));
5700 if ( tconn->kstc_type != kstt_sender &&
5701 tconn->kstc_type != kstt_child) {
5704 spin_unlock(&(tconn->kstc_lock));
5709 if (tconn->kstc_state != ksts_connected) {
5712 spin_unlock(&(tconn->kstc_lock));
5717 if (tconn->kstc_type == kstt_sender) {
5718 KsChain = &(tconn->sender.kstc_recv);
5720 LASSERT(tconn->kstc_type == kstt_child);
5721 KsChain = &(tconn->child.kstc_recv);
5725 KsTsduMgr = &(KsChain->Expedited);
5727 KsTsduMgr = &(KsChain->Normal);
5732 if (list_empty(&(KsTsduMgr->TsduList))) {
5735 // It's a notification event. We need reset it to
5736 // un-signaled state in case there no any tsdus.
5739 KeResetEvent(&(KsTsduMgr->Event));
5743 KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
5744 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
5746 /* remove the KsTsdu from TsduMgr list to release the lock */
5747 list_del(&(KsTsdu->Link));
5748 KsTsduMgr->NumOfTsdu--;
5750 spin_unlock(&(tconn->kstc_lock));
5752 while ((ULONG)size > BytesRecved) {
5754 ULONG BytesCopied = 0;
5755 ULONG BytesToCopy = 0;
5756 ULONG StartOffset = 0;
5758 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5759 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5760 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5762 if ( TSDU_TYPE_DAT == KsTsduDat->TsduType ||
5763 TSDU_TYPE_BUF == KsTsduBuf->TsduType ) {
5767 // Data Tsdu Unit ...
5770 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
5772 if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
5773 /* data is not ready yet*/
5774 KeResetEvent(&(KsTsduMgr->Event));
5775 printk("ks_recv_mdl: KsTsduDat (%xh) is not ready yet !!!!!!!\n", KsTsduDat);
5779 Buffer = &KsTsduDat->Data[0];
5780 StartOffset = KsTsduDat->StartOffset;
5781 if (KsTsduDat->DataLength - KsTsduDat->StartOffset > size - BytesRecved) {
5782 /* Recvmsg requst could be statisfied ... */
5783 BytesToCopy = size - BytesRecved;
5785 BytesToCopy = KsTsduDat->DataLength - KsTsduDat->StartOffset;
5790 if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
5791 /* data is not ready yet*/
5792 KeResetEvent(&(KsTsduMgr->Event));
5793 DbgPrint("ks_recv_mdl: KsTsduBuf (%xh) is not ready yet !!!!!!!\n", KsTsduBuf);
5797 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
5798 Buffer = KsTsduBuf->UserBuffer;
5799 StartOffset = KsTsduBuf->StartOffset;
5801 if (KsTsduBuf->DataLength - KsTsduBuf->StartOffset > size - BytesRecved) {
5802 /* Recvmsg requst could be statisfied ... */
5803 BytesToCopy = size - BytesRecved;
5805 BytesToCopy = KsTsduBuf->DataLength - KsTsduBuf->StartOffset;
5809 if (BytesToCopy > 0) {
5810 Status = TdiCopyBufferToMdl(
5819 if (NT_SUCCESS(Status)) {
5821 if (BytesToCopy != BytesCopied) {
5822 cfs_enter_debugger();
5825 BytesRecved += BytesCopied;
5826 RecvedOnce += BytesCopied;
5830 cfs_enter_debugger();
5832 if (STATUS_BUFFER_OVERFLOW == Status) {
5837 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
5839 KsTsduDat->StartOffset += BytesCopied;
5841 if (KsTsduDat->StartOffset == KsTsduDat->DataLength) {
5842 KsTsdu->StartOffset += KsTsduDat->TotalLength;
5847 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
5848 KsTsduBuf->StartOffset += BytesCopied;
5849 if (KsTsduBuf->StartOffset == KsTsduBuf->DataLength) {
5850 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
5851 /* now we need release the buf to system pool */
5852 ExFreePool(KsTsduBuf->UserBuffer);
5856 } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
5859 // MDL Tsdu Unit ...
5862 if (KsTsduMdl->DataLength > size - BytesRecved) {
5864 /* Recvmsg requst could be statisfied ... */
5866 BytesToCopy = size - BytesRecved;
5870 BytesToCopy = KsTsduMdl->DataLength;
5873 Status = KsCopyMdlChainToMdlChain(
5875 KsTsduMdl->StartOffset,
5882 if (NT_SUCCESS(Status)) {
5884 if (BytesToCopy != BytesCopied) {
5885 cfs_enter_debugger();
5888 KsTsduMdl->StartOffset += BytesCopied;
5889 KsTsduMdl->DataLength -= BytesCopied;
5891 BytesRecved += BytesCopied;
5892 RecvedOnce += BytesCopied;
5894 cfs_enter_debugger();
5897 if (0 == KsTsduMdl->DataLength) {
5900 // Call TdiReturnChainedReceives to release the Tsdu memory
5903 TdiReturnChainedReceives(
5904 &(KsTsduMdl->Descriptor),
5907 KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
5911 printk("ks_recv_mdl: unknown tsdu slot: slot = %x type = %x Start= %x\n",
5912 KsTsduDat, KsTsduDat->TsduType, KsTsduDat->StartOffset, KsTsduDat->DataLength);
5913 printk(" Tsdu = %x Magic=%x: Start = %x Last = %x Length = %x",
5914 KsTsdu, KsTsdu->Magic, KsTsdu->StartOffset, KsTsdu->LastOffset, KsTsdu->TotalLength);
5915 cfs_enter_debugger();
5918 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
5921 // KsTsdu is empty now, we need free it ...
5924 KsPutKsTsdu(KsTsdu);
5931 spin_lock(&(tconn->kstc_lock));
5933 /* we need attach the KsTsdu to the list header */
5935 KsTsduMgr->NumOfTsdu++;
5936 list_add(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
5937 } else if ((ULONG)size > BytesRecved) {
5942 if (KsTsduMgr->TotalBytes < RecvedOnce) {
5943 cfs_enter_debugger();
5944 KsTsduMgr->TotalBytes = 0;
5946 KsTsduMgr->TotalBytes -= RecvedOnce;
5949 spin_unlock(&(tconn->kstc_lock));
5951 if (NT_SUCCESS(Status)) {
5953 if ((BytesRecved < (ulong_ptr)size) && (!bIsNonBlock)) {
5955 KeWaitForSingleObject(
5956 &(KsTsduMgr->Event),
5966 if (bIsNonBlock && (BytesRecved == 0)) {
5975 ks_put_tconn(tconn);
5978 KsPrint((1, "ks_recv_mdl: recvieving %d bytes ...\n", rc));
5980 KsPrint((0, "ks_recv_mdl: recvieving error code = %d Stauts = %xh ...\n", rc, Status));
5983 /* release the chained mdl */
5984 ks_release_mdl(mdl, FALSE);
5992 * initialize the global data in ksockal_data
5998 * int: ks error code
6009 /* initialize tconn related globals */
6010 RtlZeroMemory(&ks_data, sizeof(ks_data_t));
6012 spin_lock_init(&ks_data.ksnd_tconn_lock);
6013 CFS_INIT_LIST_HEAD(&ks_data.ksnd_tconns);
6014 cfs_init_event(&ks_data.ksnd_tconn_exit, TRUE, FALSE);
6016 ks_data.ksnd_tconn_slab = cfs_mem_cache_create(
6017 "tcon", sizeof(ksock_tconn_t) , 0, 0);
6019 if (!ks_data.ksnd_tconn_slab) {
6024 /* initialize tsdu related globals */
6026 spin_lock_init(&ks_data.ksnd_tsdu_lock);
6027 CFS_INIT_LIST_HEAD(&ks_data.ksnd_freetsdus);
6028 ks_data.ksnd_tsdu_size = TDINAL_TSDU_DEFAULT_SIZE; /* 64k */
6029 ks_data.ksnd_tsdu_slab = cfs_mem_cache_create(
6030 "tsdu", ks_data.ksnd_tsdu_size, 0, 0);
6032 if (!ks_data.ksnd_tsdu_slab) {
6034 cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
6035 ks_data.ksnd_tconn_slab = NULL;
6039 /* initialize daemon related globals */
6041 spin_lock_init(&ks_data.ksnd_daemon_lock);
6042 CFS_INIT_LIST_HEAD(&ks_data.ksnd_daemons);
6043 cfs_init_event(&ks_data.ksnd_daemon_exit, TRUE, FALSE);
6045 KsRegisterPnpHandlers();
6055 * finalize the global data in ksockal_data
6061 * int: ks error code
6070 PKS_TSDU KsTsdu = NULL;
6071 struct list_head * list = NULL;
6073 /* clean up the pnp handler and address slots */
6074 KsDeregisterPnpHandlers();
6076 /* we need wait until all the tconn are freed */
6077 spin_lock(&(ks_data.ksnd_tconn_lock));
6079 if (list_empty(&(ks_data.ksnd_tconns))) {
6080 cfs_wake_event(&ks_data.ksnd_tconn_exit);
6082 spin_unlock(&(ks_data.ksnd_tconn_lock));
6084 /* now wait on the tconn exit event */
6085 cfs_wait_event(&ks_data.ksnd_tconn_exit, 0);
6087 /* it's safe to delete the tconn slab ... */
6088 cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
6089 ks_data.ksnd_tconn_slab = NULL;
6091 /* clean up all the tsud buffers in the free list */
6092 spin_lock(&(ks_data.ksnd_tsdu_lock));
6093 list_for_each (list, &ks_data.ksnd_freetsdus) {
6094 KsTsdu = list_entry (list, KS_TSDU, Link);
6097 ks_data.ksnd_tsdu_slab,
6100 spin_unlock(&(ks_data.ksnd_tsdu_lock));
6102 /* it's safe to delete the tsdu slab ... */
6103 cfs_mem_cache_destroy(ks_data.ksnd_tsdu_slab);
6104 ks_data.ksnd_tsdu_slab = NULL;
6106 /* good! it's smooth to do the cleaning up...*/
6110 * ks_create_child_tconn
6111 * Create the backlog child connection for a listener
6114 * parent: the listener daemon connection
6117 * the child connection or NULL in failure
6124 ks_create_child_tconn(
6125 ksock_tconn_t * parent
6129 ksock_tconn_t * backlog;
6131 /* allocate the tdi connecton object */
6132 backlog = ks_create_tconn();
6138 /* initialize the tconn as a child */
6139 ks_init_child(backlog);
6143 if (ks_bind_tconn(backlog, parent, 0, 0) < 0) {
6144 ks_free_tconn(backlog);
6149 /* open the connection object */
6150 status = KsOpenConnection(
6151 &(backlog->kstc_dev),
6153 &(backlog->child.kstc_info.Handle),
6154 &(backlog->child.kstc_info.FileObject)
6157 if (!NT_SUCCESS(status)) {
6159 ks_put_tconn(backlog);
6161 cfs_enter_debugger();
6165 /* associate it now ... */
6166 status = KsAssociateAddress(
6167 backlog->kstc_addr.Handle,
6168 backlog->child.kstc_info.FileObject
6171 if (!NT_SUCCESS(status)) {
6173 ks_put_tconn(backlog);
6175 cfs_enter_debugger();
6179 backlog->kstc_state = ksts_associated;
6187 * ks_replenish_backlogs(
6188 * to replenish the backlogs listening...
6191 * tconn: the parent listen tdi connect
6192 * nbacklog: number fo child connections in queue
6202 ks_replenish_backlogs(
6203 ksock_tconn_t * parent,
6207 ksock_tconn_t * backlog;
6210 /* calculate how many backlogs needed */
6211 if ( ( parent->listener.kstc_listening.num +
6212 parent->listener.kstc_accepted.num ) < nbacklog ) {
6213 n = nbacklog - ( parent->listener.kstc_listening.num +
6214 parent->listener.kstc_accepted.num );
6221 /* create the backlog child tconn */
6222 backlog = ks_create_child_tconn(parent);
6224 spin_lock(&(parent->kstc_lock));
6227 spin_lock(&backlog->kstc_lock);
6228 /* attch it into the listing list of daemon */
6229 list_add( &backlog->child.kstc_link,
6230 &parent->listener.kstc_listening.list );
6231 parent->listener.kstc_listening.num++;
6233 backlog->child.kstc_queued = TRUE;
6234 spin_unlock(&backlog->kstc_lock);
6236 cfs_enter_debugger();
6239 spin_unlock(&(parent->kstc_lock));
6245 * setup the listener tdi connection and make it listen
6246 * on the user specified ip address and port.
6249 * tconn: the parent listen tdi connect
6250 * nbacklog: number fo child connections in queue
6253 * ks error code >=: success; otherwise error.
6260 ks_start_listen(ksock_tconn_t *tconn, int nbacklog)
6264 /* now replenish the backlogs */
6265 ks_replenish_backlogs(tconn, nbacklog);
6267 /* set the event callback handlers */
6268 rc = ks_set_handlers(tconn);
6274 spin_lock(&(tconn->kstc_lock));
6275 tconn->listener.nbacklog = nbacklog;
6276 tconn->kstc_state = ksts_listening;
6277 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
6278 spin_unlock(&(tconn->kstc_lock));
6284 ks_stop_listen(ksock_tconn_t *tconn)
6286 struct list_head * list;
6287 ksock_tconn_t * backlog;
6289 /* reset all tdi event callbacks to NULL */
6290 ks_reset_handlers (tconn);
6292 spin_lock(&tconn->kstc_lock);
6294 cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
6296 /* cleanup all the listening backlog child connections */
6297 list_for_each (list, &(tconn->listener.kstc_listening.list)) {
6298 backlog = list_entry(list, ksock_tconn_t, child.kstc_link);
6300 /* destory and free it */
6301 ks_put_tconn(backlog);
6304 spin_unlock(&tconn->kstc_lock);
6306 /* wake up it from the waiting on new incoming connections */
6307 KeSetEvent(&tconn->listener.kstc_accept_event, 0, FALSE);
6309 /* free the listening daemon tconn */
6310 ks_put_tconn(tconn);
6315 * ks_wait_child_tconn
6316 * accept a child connection from peer
6319 * parent: the daemon tdi connection listening
6320 * child: to contain the accepted connection
6330 ks_wait_child_tconn(
6331 ksock_tconn_t * parent,
6332 ksock_tconn_t ** child
6335 struct list_head * tmp;
6336 ksock_tconn_t * backlog = NULL;
6338 ks_replenish_backlogs(parent, parent->listener.nbacklog);
6340 spin_lock(&(parent->kstc_lock));
6342 if (parent->listener.kstc_listening.num <= 0) {
6343 spin_unlock(&(parent->kstc_lock));
6349 /* check the listening queue and try to search the accepted connecton */
6351 list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
6352 backlog = list_entry (tmp, ksock_tconn_t, child.kstc_link);
6354 spin_lock(&(backlog->kstc_lock));
6356 if (backlog->child.kstc_accepted) {
6358 LASSERT(backlog->kstc_state == ksts_connected);
6359 LASSERT(backlog->child.kstc_busy);
6361 list_del(&(backlog->child.kstc_link));
6362 list_add(&(backlog->child.kstc_link),
6363 &(parent->listener.kstc_accepted.list));
6364 parent->listener.kstc_accepted.num++;
6365 parent->listener.kstc_listening.num--;
6366 backlog->child.kstc_queueno = 1;
6368 spin_unlock(&(backlog->kstc_lock));
6372 spin_unlock(&(backlog->kstc_lock));
6377 spin_unlock(&(parent->kstc_lock));
6379 /* we need wait until new incoming connections are requested
6380 or the case of shuting down the listenig daemon thread */
6381 if (backlog == NULL) {
6385 Status = KeWaitForSingleObject(
6386 &(parent->listener.kstc_accept_event),
6393 spin_lock(&(parent->kstc_lock));
6395 /* check whether it's exptected to exit ? */
6396 if (!cfs_is_flag_set(parent->kstc_flags, KS_TCONN_DAEMON_STARTED)) {
6397 spin_unlock(&(parent->kstc_lock));
6404 /* query the local ip address of the connection */
6405 ks_query_local_ipaddr(backlog);
6413 int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask)
6415 ks_addr_slot_t * slot = NULL;
6416 PLIST_ENTRY list = NULL;
6418 spin_lock(&ks_data.ksnd_addrs_lock);
6420 list = ks_data.ksnd_addrs_list.Flink;
6421 while (list != &ks_data.ksnd_addrs_list) {
6422 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
6423 if (_stricmp(name, &slot->iface[0]) == 0) {
6425 *ip = slot->ip_addr;
6426 *mask = slot->netmask;
6433 spin_unlock(&ks_data.ksnd_addrs_lock);
6435 return (int)(slot == NULL);
6438 int libcfs_ipif_enumerate(char ***names)
6440 ks_addr_slot_t * slot = NULL;
6441 PLIST_ENTRY list = NULL;
6444 spin_lock(&ks_data.ksnd_addrs_lock);
6446 *names = cfs_alloc(sizeof(char *) * ks_data.ksnd_naddrs, CFS_ALLOC_ZERO);
6447 if (*names == NULL) {
6451 list = ks_data.ksnd_addrs_list.Flink;
6452 while (list != &ks_data.ksnd_addrs_list) {
6453 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
6455 (*names)[nips++] = slot->iface;
6456 cfs_assert(nips <= ks_data.ksnd_naddrs);
6459 cfs_assert(nips == ks_data.ksnd_naddrs);
6463 spin_unlock(&ks_data.ksnd_addrs_lock);
6467 void libcfs_ipif_free_enumeration(char **names, int n)
6474 int libcfs_sock_listen(struct socket **sockp, __u32 ip, int port, int backlog)
6477 ksock_tconn_t * parent;
6479 parent = ks_create_tconn();
6485 /* initialize the tconn as a listener */
6486 ks_init_listener(parent);
6488 /* bind the daemon->tconn */
6489 rc = ks_bind_tconn(parent, NULL, ip, (unsigned short)port);
6492 ks_free_tconn(parent);
6496 /* create listening children and make it to listen state*/
6497 rc = ks_start_listen(parent, backlog);
6499 ks_stop_listen(parent);
6510 int libcfs_sock_accept(struct socket **newsockp, struct socket *sock)
6512 /* wait for incoming connecitons */
6513 return ks_wait_child_tconn(sock, newsockp);
6516 void libcfs_sock_abort_accept(struct socket *sock)
6518 LASSERT(sock->kstc_type == kstt_listener);
6520 spin_lock(&(sock->kstc_lock));
6522 /* clear the daemon flag */
6523 cfs_clear_flag(sock->kstc_flags, KS_TCONN_DAEMON_STARTED);
6525 /* wake up it from the waiting on new incoming connections */
6526 KeSetEvent(&sock->listener.kstc_accept_event, 0, FALSE);
6528 spin_unlock(&(sock->kstc_lock));
6532 * libcfs_sock_connect
6533 * build a conntion between local ip/port and the peer ip/port.
6536 * laddr: local ip address
6537 * lport: local port number
6538 * paddr: peer's ip address
6539 * pport: peer's port number
6542 * int: return code ...
6549 int libcfs_sock_connect(struct socket **sockp, int *fatal,
6550 __u32 local_ip, int local_port,
6551 __u32 peer_ip, int peer_port)
6553 ksock_tconn_t * tconn = NULL;
6558 KsPrint((1, "libcfs_sock_connect: connecting to %x:%d with %x:%d...\n",
6559 peer_ip, peer_port, local_ip, local_port ));
6561 /* create the tdi connecion structure */
6562 tconn = ks_create_tconn();
6568 /* initialize the tdi sender connection */
6569 ks_init_sender(tconn);
6571 /* bind the local ip address with the tconn */
6572 rc = ks_bind_tconn(tconn, NULL, local_ip, (unsigned short)local_port);
6574 KsPrint((0, "libcfs_sock_connect: failed to bind address %x:%d...\n",
6575 local_ip, local_port ));
6576 ks_free_tconn(tconn);
6580 /* connect to the remote peer */
6581 rc = ks_build_tconn(tconn, peer_ip, (unsigned short)peer_port);
6583 KsPrint((0, "libcfs_sock_connect: failed to connect %x:%d ...\n",
6584 peer_ip, peer_port ));
6586 ks_put_tconn(tconn);
6597 int libcfs_sock_setbuf(struct socket *socket, int txbufsize, int rxbufsize)
6602 int libcfs_sock_getbuf(struct socket *socket, int *txbufsize, int *rxbufsize)
6607 int libcfs_sock_getaddr(struct socket *socket, int remote, __u32 *ip, int *port)
6609 PTRANSPORT_ADDRESS taddr = NULL;
6611 spin_lock(&socket->kstc_lock);
6613 if (socket->kstc_type == kstt_sender) {
6614 taddr = socket->sender.kstc_info.Remote;
6615 } else if (socket->kstc_type == kstt_child) {
6616 taddr = socket->child.kstc_info.Remote;
6619 taddr = &(socket->kstc_addr.Tdi);
6623 PTDI_ADDRESS_IP addr = (PTDI_ADDRESS_IP)(&(taddr->Address[0].Address));
6625 *ip = ntohl (addr->in_addr);
6627 *port = ntohs (addr->sin_port);
6629 spin_unlock(&socket->kstc_lock);
6633 spin_unlock(&socket->kstc_lock);
6637 int libcfs_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
6644 while (nob > offset) {
6646 /* lock the user buffer */
6647 rc = ks_lock_buffer( (char *)buffer + offset,
6648 FALSE, nob - offset, IoReadAccess, &mdl );
6654 /* send out the whole mdl */
6655 rc = ks_send_mdl( sock, NULL, mdl, nob - offset, 0 );
6667 int libcfs_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
6674 while (nob > offset) {
6676 /* lock the user buffer */
6677 rc = ks_lock_buffer( (char *)buffer + offset,
6678 FALSE, nob - offset, IoWriteAccess, &mdl );
6684 /* recv the requested buffer */
6685 rc = ks_recv_mdl( sock, mdl, nob - offset, 0 );
6697 void libcfs_sock_release(struct socket *sock)
6699 if (sock->kstc_type == kstt_listener &&
6700 sock->kstc_state == ksts_listening) {
6701 ks_stop_listen(sock);