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 <libcfs/kp30.h>
26 #include <lnet/lnet.h>
28 #define TDILND_MODULE_NAME L"Tdilnd"
33 ks_tdi_send_flags(ULONG SockFlags)
37 if (cfs_is_flag_set(SockFlags, MSG_OOB)) {
38 cfs_set_flag(TdiFlags, TDI_SEND_EXPEDITED);
41 if (cfs_is_flag_set(SockFlags, MSG_MORE)) {
42 cfs_set_flag(TdiFlags, TDI_SEND_PARTIAL);
45 if (cfs_is_flag_set(SockFlags, MSG_DONTWAIT)) {
46 cfs_set_flag(TdiFlags, TDI_SEND_NON_BLOCKING);
53 KsIrpCompletionRoutine(
54 IN PDEVICE_OBJECT DeviceObject,
59 if (NULL != Context) {
60 KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
63 return STATUS_MORE_PROCESSING_REQUIRED;
65 UNREFERENCED_PARAMETER(DeviceObject);
66 UNREFERENCED_PARAMETER(Irp);
72 * Allocate a new IRP and initialize it to be issued to tdi
75 * DeviceObject: device object created by the underlying
76 * TDI transport driver
79 * PRIP: the allocated Irp in success or NULL in failure.
87 IN PDEVICE_OBJECT DeviceObject
91 PIO_STACK_LOCATION IrpSp;
94 // Allocating the IRP ...
97 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
102 // Getting the Next Stack Location ...
105 IrpSp = IoGetNextIrpStackLocation(Irp);
108 // Initializing Irp ...
111 IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
112 IrpSp->Parameters.DeviceIoControl.IoControlCode = 0;
120 * Issue the Irp to the underlying tdi driver
123 * DeviceObject: the device object created by TDI driver
124 * Irp: the I/O request packet to be processed
125 * bSynchronous: synchronous or not. If true, we need wait
126 * until the process is finished.
127 * Information: returned info
130 * NTSTATUS: kernel status code
138 IN PDEVICE_OBJECT DeviceObject,
140 IN BOOLEAN bSynchronous,
141 OUT PULONG Information
151 SynchronizationEvent,
156 IoSetCompletionRoutine(
158 KsIrpCompletionRoutine,
166 Status = IoCallDriver(DeviceObject, Irp);
170 if (STATUS_PENDING == Status) {
172 Status = KeWaitForSingleObject(
181 Status = Irp->IoStatus.Status;
184 *Information = (ULONG)(Irp->IoStatus.Information);
187 Irp->MdlAddress = NULL;
191 if (!NT_SUCCESS(Status)) {
193 KsPrint((2, "KsSubmitTdiIrp: Error when submitting the Irp: Status = %xh (%s) ...\n",
194 Status, KsNtStatusToString(Status)));
204 * Open the Control Channel Object ...
207 * DeviceName: the device name to be opened
208 * Handle: opened handle in success case
209 * FileObject: the fileobject of the device
212 * NTSTATUS: kernel status code (STATUS_SUCCESS
213 * or other error code)
221 IN PUNICODE_STRING DeviceName,
223 OUT PFILE_OBJECT * FileObject
226 NTSTATUS Status = STATUS_SUCCESS;
228 OBJECT_ATTRIBUTES ObjectAttributes;
229 IO_STATUS_BLOCK IoStatus;
232 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
238 InitializeObjectAttributes(
241 OBJ_CASE_INSENSITIVE |
247 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
250 // Creating the Transport Address Object ...
253 Status = ZwCreateFile(
255 FILE_READ_DATA | FILE_WRITE_DATA,
259 FILE_ATTRIBUTE_NORMAL,
260 FILE_SHARE_READ | FILE_SHARE_WRITE,
268 if (NT_SUCCESS(Status)) {
271 // Now Obtaining the FileObject of the Transport Address ...
274 Status = ObReferenceObjectByHandle(
283 if (!NT_SUCCESS(Status)) {
285 cfs_enter_debugger();
291 cfs_enter_debugger();
300 * Release the Control Channel Handle and FileObject
303 * Handle: the channel handle to be released
304 * FileObject: the fileobject to be released
307 * NTSTATUS: kernel status code (STATUS_SUCCESS
308 * or other error code)
317 IN PFILE_OBJECT FileObject
320 NTSTATUS Status = STATUS_SUCCESS;
322 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
326 ObDereferenceObject(FileObject);
331 Status = ZwClose(Handle);
334 ASSERT(NT_SUCCESS(Status));
342 * Open the tdi address object
345 * DeviceName: device name of the address object
346 * pAddress: tdi address of the address object
347 * AddressLength: length in bytes of the tdi address
348 * Handle: the newly opened handle
349 * FileObject: the newly opened fileobject
352 * NTSTATUS: kernel status code (STATUS_SUCCESS
353 * or other error code)
361 IN PUNICODE_STRING DeviceName,
362 IN PTRANSPORT_ADDRESS pAddress,
363 IN ULONG AddressLength,
365 OUT PFILE_OBJECT * FileObject
368 NTSTATUS Status = STATUS_SUCCESS;
370 PFILE_FULL_EA_INFORMATION Ea = NULL;
372 UCHAR EaBuffer[EA_MAX_LENGTH];
374 OBJECT_ATTRIBUTES ObjectAttributes;
375 IO_STATUS_BLOCK IoStatus;
378 // Building EA for the Address Object to be Opened ...
381 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
382 Ea->NextEntryOffset = 0;
384 Ea->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
385 Ea->EaValueLength = (USHORT)AddressLength;
392 &(Ea->EaName[Ea->EaNameLength + 1]),
396 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
397 Ea->EaNameLength + AddressLength;
399 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
406 InitializeObjectAttributes(
409 OBJ_CASE_INSENSITIVE |
415 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
418 // Creating the Transport Address Object ...
421 Status = ZwCreateFile(
423 FILE_READ_DATA | FILE_WRITE_DATA,
427 FILE_ATTRIBUTE_NORMAL,
428 FILE_SHARE_READ | FILE_SHARE_WRITE, /* 0: DON'T REUSE */
436 if (NT_SUCCESS(Status)) {
439 // Now Obtaining the FileObject of the Transport Address ...
442 Status = ObReferenceObjectByHandle(
451 if (!NT_SUCCESS(Status)) {
453 cfs_enter_debugger();
459 cfs_enter_debugger();
467 * Release the Hanlde and FileObject of an opened tdi
471 * Handle: the handle to be released
472 * FileObject: the fileobject to be released
475 * NTSTATUS: kernel status code (STATUS_SUCCESS
476 * or other error code)
485 IN PFILE_OBJECT FileObject
488 NTSTATUS Status = STATUS_SUCCESS;
492 ObDereferenceObject(FileObject);
497 Status = ZwClose(Handle);
500 ASSERT(NT_SUCCESS(Status));
508 * Open a tdi connection object
511 * DeviceName: device name of the connection object
512 * ConnectionContext: the connection context
513 * Handle: the newly opened handle
514 * FileObject: the newly opened fileobject
517 * NTSTATUS: kernel status code (STATUS_SUCCESS
518 * or other error code)
526 IN PUNICODE_STRING DeviceName,
527 IN CONNECTION_CONTEXT ConnectionContext,
529 OUT PFILE_OBJECT * FileObject
532 NTSTATUS Status = STATUS_SUCCESS;
534 PFILE_FULL_EA_INFORMATION Ea = NULL;
536 UCHAR EaBuffer[EA_MAX_LENGTH];
538 OBJECT_ATTRIBUTES ObjectAttributes;
539 IO_STATUS_BLOCK IoStatus;
542 // Building EA for the Address Object to be Opened ...
545 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
546 Ea->NextEntryOffset = 0;
548 Ea->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
549 Ea->EaValueLength = (USHORT)sizeof(CONNECTION_CONTEXT);
552 TdiConnectionContext,
556 &(Ea->EaName[Ea->EaNameLength + 1]),
558 sizeof(CONNECTION_CONTEXT)
560 EaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
561 Ea->EaNameLength + 1 + sizeof(CONNECTION_CONTEXT);
563 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
570 InitializeObjectAttributes(
573 OBJ_CASE_INSENSITIVE |
579 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
582 // Creating the Connection Object ...
585 Status = ZwCreateFile(
587 FILE_READ_DATA | FILE_WRITE_DATA,
591 FILE_ATTRIBUTE_NORMAL,
600 if (NT_SUCCESS(Status)) {
603 // Now Obtaining the FileObject of the Transport Address ...
606 Status = ObReferenceObjectByHandle(
615 if (!NT_SUCCESS(Status)) {
617 cfs_enter_debugger();
623 cfs_enter_debugger();
631 * Release the Hanlde and FileObject of an opened tdi
635 * Handle: the handle to be released
636 * FileObject: the fileobject to be released
639 * NTSTATUS: kernel status code (STATUS_SUCCESS
640 * or other error code)
649 IN PFILE_OBJECT FileObject
652 NTSTATUS Status = STATUS_SUCCESS;
656 ObDereferenceObject(FileObject);
661 Status = ZwClose(Handle);
664 ASSERT(NT_SUCCESS(Status));
672 * Associate an address object with a connection object
675 * AddressHandle: the handle of the address object
676 * ConnectionObject: the FileObject of the connection
679 * NTSTATUS: kernel status code (STATUS_SUCCESS
680 * or other error code)
688 IN HANDLE AddressHandle,
689 IN PFILE_OBJECT ConnectionObject
693 PDEVICE_OBJECT DeviceObject;
697 // Getting the DeviceObject from Connection FileObject
700 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
703 // Building Tdi Internal Irp ...
706 Irp = KsBuildTdiIrp(DeviceObject);
710 Status = STATUS_INSUFFICIENT_RESOURCES;
715 // Assocating the Address Object with the Connection Object
718 TdiBuildAssociateAddress(
728 // Calling the Transprot Driver with the Prepared Irp
731 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
739 * KsDisassociateAddress
740 * Disassociate the connection object (the relationship will
741 * the corresponding address object will be dismissed. )
744 * ConnectionObject: the FileObject of the connection
747 * NTSTATUS: kernel status code (STATUS_SUCCESS
748 * or other error code)
755 KsDisassociateAddress(
756 IN PFILE_OBJECT ConnectionObject
760 PDEVICE_OBJECT DeviceObject;
764 // Getting the DeviceObject from Connection FileObject
767 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
770 // Building Tdi Internal Irp ...
773 Irp = KsBuildTdiIrp(DeviceObject);
777 Status = STATUS_INSUFFICIENT_RESOURCES;
782 // Disassocating the Address Object with the Connection Object
785 TdiBuildDisassociateAddress(
794 // Calling the Transprot Driver with the Prepared Irp
797 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
807 // Connection Control Event Callbacks
815 // Tcp Event Callbacks
819 TDI_EVENT_RECEIVE_EXPEDITED
820 TDI_EVENT_CHAINED_RECEIVE
821 TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
824 // Udp Event Callbacks
827 TDI_EVENT_RECEIVE_DATAGRAM
828 TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
835 * Set the tdi event callbacks with an address object
838 * AddressObject: the FileObject of the address object
839 * EventContext: the parameter for the callbacks
840 * Handlers: the handlers indictor array
843 * NTSTATUS: kernel status code (STATUS_SUCCESS
844 * or other error code)
852 IN PFILE_OBJECT AddressObject, // Address File Object
853 IN PVOID EventContext, // Context for Handlers
854 IN PKS_EVENT_HANDLERS Handlers // Handlers Indictor
857 NTSTATUS Status = STATUS_SUCCESS;
858 PDEVICE_OBJECT DeviceObject;
861 DeviceObject = IoGetRelatedDeviceObject(AddressObject);
863 for (i=0; i < TDI_EVENT_MAXIMUM_HANDLER; i++) {
866 // Setup the tdi event callback handler if requested.
869 if (Handlers->IsActive[i]) {
874 // Building Tdi Internal Irp ...
877 Irp = KsBuildTdiIrp(DeviceObject);
881 Status = STATUS_INSUFFICIENT_RESOURCES;
886 // Building the Irp to set the Event Handler ...
889 TdiBuildSetEventHandler(
895 i, /* tdi event type */
896 Handlers->Handler[i], /* tdi event handler */
897 EventContext /* context for the handler */
901 // Calling the Transprot Driver with the Prepared Irp
904 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
907 // tcp/ip tdi does not support these two event callbacks
910 if ((!NT_SUCCESS(Status)) && ( i == TDI_EVENT_SEND_POSSIBLE ||
911 i == TDI_EVENT_CHAINED_RECEIVE_EXPEDITED )) {
912 cfs_enter_debugger();
913 Status = STATUS_SUCCESS;
917 if (!NT_SUCCESS(Status)) {
918 cfs_enter_debugger();
927 if (!NT_SUCCESS(Status)) {
929 KsPrint((2, "KsSetEventHandlers: Error Status = %xh (%s)\n",
930 Status, KsNtStatusToString(Status) ));
940 * Query the address of the FileObject specified
943 * FileObject: the FileObject to be queried
944 * AddressInfo: buffer to contain the address info
945 * AddressSize: length of the AddressInfo buffer
948 * NTSTATUS: kernel status code (STATUS_SUCCESS
949 * or other error code)
957 PFILE_OBJECT FileObject,
958 PTDI_ADDRESS_INFO AddressInfo,
962 NTSTATUS Status = STATUS_UNSUCCESSFUL;
965 PDEVICE_OBJECT DeviceObject;
967 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
969 DeviceObject = IoGetRelatedDeviceObject(FileObject);
971 RtlZeroMemory(AddressInfo, *(AddressSize));
974 // Allocating the Tdi Setting Irp ...
977 Irp = KsBuildTdiIrp(DeviceObject);
981 Status = STATUS_INSUFFICIENT_RESOURCES;
986 // Locking the User Buffer / Allocating a MDL for it
989 Status = KsLockUserBuffer(
997 if (!NT_SUCCESS(Status)) {
1006 LASSERT(NT_SUCCESS(Status));
1008 TdiBuildQueryInformation(
1014 TDI_QUERY_ADDRESS_INFO,
1018 Status = KsSubmitTdiIrp(
1025 KsReleaseMdl(Mdl, FALSE);
1028 if (!NT_SUCCESS(Status)) {
1030 cfs_enter_debugger();
1031 //TDI_BUFFER_OVERFLOW
1038 * KsQueryProviderInfo
1039 * Query the underlying transport device's information
1042 * TdiDeviceName: the transport device's name string
1043 * ProviderInfo: TDI_PROVIDER_INFO struncture
1046 * NTSTATUS: Nt system status code
1053 KsQueryProviderInfo(
1054 PWSTR TdiDeviceName,
1055 PTDI_PROVIDER_INFO ProviderInfo
1058 NTSTATUS Status = STATUS_SUCCESS;
1063 UNICODE_STRING ControlName;
1066 PFILE_OBJECT FileObject;
1067 PDEVICE_OBJECT DeviceObject;
1069 ULONG ProviderSize = 0;
1071 RtlInitUnicodeString(&ControlName, TdiDeviceName);
1074 // Open the Tdi Control Channel
1077 Status = KsOpenControl(
1083 if (!NT_SUCCESS(Status)) {
1085 KsPrint((2, "KsQueryProviderInfo: Fail to open the tdi control channel.\n"));
1090 // Obtain The Related Device Object
1093 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1095 ProviderSize = sizeof(TDI_PROVIDER_INFO);
1096 RtlZeroMemory(ProviderInfo, ProviderSize);
1099 // Allocating the Tdi Setting Irp ...
1102 Irp = KsBuildTdiIrp(DeviceObject);
1106 Status = STATUS_INSUFFICIENT_RESOURCES;
1111 // Locking the User Buffer / Allocating a MDL for it
1114 Status = KsLockUserBuffer(
1122 if (!NT_SUCCESS(Status)) {
1131 LASSERT(NT_SUCCESS(Status));
1133 TdiBuildQueryInformation(
1139 TDI_QUERY_PROVIDER_INFO,
1143 Status = KsSubmitTdiIrp(
1150 KsReleaseMdl(Mdl, FALSE);
1153 if (!NT_SUCCESS(Status)) {
1155 cfs_enter_debugger();
1156 //TDI_BUFFER_OVERFLOW
1159 KsCloseControl(Handle, FileObject);
1165 * KsQueryConnectionInfo
1166 * Query the connection info of the FileObject specified
1167 * (some statics data of the traffic)
1170 * FileObject: the FileObject to be queried
1171 * ConnectionInfo: buffer to contain the connection info
1172 * ConnectionSize: length of the ConnectionInfo buffer
1175 * NTSTATUS: kernel status code (STATUS_SUCCESS
1176 * or other error code)
1183 KsQueryConnectionInfo(
1184 PFILE_OBJECT ConnectionObject,
1185 PTDI_CONNECTION_INFO ConnectionInfo,
1186 PULONG ConnectionSize
1189 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1192 PDEVICE_OBJECT DeviceObject;
1194 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
1196 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
1198 RtlZeroMemory(ConnectionInfo, *(ConnectionSize));
1201 // Allocating the Tdi Query Irp ...
1204 Irp = KsBuildTdiIrp(DeviceObject);
1208 Status = STATUS_INSUFFICIENT_RESOURCES;
1213 // Locking the User Buffer / Allocating a MDL for it
1216 Status = KsLockUserBuffer(
1224 if (NT_SUCCESS(Status)) {
1233 LASSERT(NT_SUCCESS(Status));
1235 TdiBuildQueryInformation(
1241 TDI_QUERY_CONNECTION_INFO,
1245 Status = KsSubmitTdiIrp(
1252 KsReleaseMdl(Mdl, FALSE);
1260 * KsInitializeTdiAddress
1261 * Initialize the tdi addresss
1264 * pTransportAddress: tdi address to be initialized
1265 * IpAddress: the ip address of object
1266 * IpPort: the ip port of the object
1269 * ULONG: the total size of the tdi address
1276 KsInitializeTdiAddress(
1277 IN OUT PTA_IP_ADDRESS pTransportAddress,
1282 pTransportAddress->TAAddressCount = 1;
1283 pTransportAddress->Address[ 0 ].AddressLength = TDI_ADDRESS_LENGTH_IP;
1284 pTransportAddress->Address[ 0 ].AddressType = TDI_ADDRESS_TYPE_IP;
1285 pTransportAddress->Address[ 0 ].Address[ 0 ].sin_port = IpPort;
1286 pTransportAddress->Address[ 0 ].Address[ 0 ].in_addr = IpAddress;
1288 return (FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) + TDI_ADDRESS_LENGTH_IP);
1292 * KsQueryTdiAddressLength
1293 * Query the total size of the tdi address
1296 * pTransportAddress: tdi address to be queried
1299 * ULONG: the total size of the tdi address
1306 KsQueryTdiAddressLength(
1307 PTRANSPORT_ADDRESS pTransportAddress
1310 ULONG TotalLength = 0;
1313 PTA_ADDRESS UNALIGNED pTaAddress = NULL;
1315 ASSERT (NULL != pTransportAddress);
1317 TotalLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) +
1318 FIELD_OFFSET(TA_ADDRESS, Address) * pTransportAddress->TAAddressCount;
1320 pTaAddress = (TA_ADDRESS UNALIGNED *)pTransportAddress->Address;
1322 for (i = 0; i < pTransportAddress->TAAddressCount; i++)
1324 TotalLength += pTaAddress->AddressLength;
1325 pTaAddress = (TA_ADDRESS UNALIGNED *)((PCHAR)pTaAddress +
1326 FIELD_OFFSET(TA_ADDRESS,Address) +
1327 pTaAddress->AddressLength );
1330 return (TotalLength);
1336 * Query the ip address of the tdi object
1339 * FileObject: tdi object to be queried
1340 * TdiAddress: TdiAddress buffer, to store the queried
1342 * AddressLength: buffer length of the TdiAddress
1345 * ULONG: the total size of the tdi ip address
1353 PFILE_OBJECT FileObject,
1355 ULONG* AddressLength
1360 PTDI_ADDRESS_INFO TdiAddressInfo;
1365 // Maximum length of TDI_ADDRESSS_INFO with one TRANSPORT_ADDRESS
1368 Length = MAX_ADDRESS_LENGTH;
1370 TdiAddressInfo = (PTDI_ADDRESS_INFO)
1371 ExAllocatePoolWithTag(
1376 if (NULL == TdiAddressInfo) {
1378 Status = STATUS_INSUFFICIENT_RESOURCES;
1383 Status = KsQueryAddressInfo(
1391 if (NT_SUCCESS(Status))
1393 if (*AddressLength < Length) {
1395 Status = STATUS_BUFFER_TOO_SMALL;
1399 *AddressLength = Length;
1402 &(TdiAddressInfo->Address),
1406 Status = STATUS_SUCCESS;
1414 if (NULL != TdiAddressInfo) {
1416 ExFreePool(TdiAddressInfo);
1424 * KsErrorEventHandler
1425 * the common error event handler callback
1428 * TdiEventContext: should be the socket
1429 * Status: the error code
1432 * Status: STATS_SUCCESS
1435 * We need not do anything in such a severe
1436 * error case. System will process it for us.
1440 KsErrorEventHandler(
1441 IN PVOID TdiEventContext,
1445 KsPrint((2, "KsErrorEventHandler called at Irql = %xh ...\n",
1446 KeGetCurrentIrql()));
1448 cfs_enter_debugger();
1450 return (STATUS_SUCCESS);
1456 * setup all the event handler callbacks
1459 * tconn: the tdi connecton object
1462 * int: ks error code
1470 ksock_tconn_t * tconn
1473 NTSTATUS status = STATUS_SUCCESS;
1474 KS_EVENT_HANDLERS handlers;
1476 /* to make sure the address object is opened already */
1477 if (tconn->kstc_addr.FileObject == NULL) {
1481 /* initialize the handlers indictor array. for sender and listenr,
1482 there are different set of callbacks. for child, we just return. */
1484 memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
1486 SetEventHandler(handlers, TDI_EVENT_ERROR, KsErrorEventHandler);
1487 SetEventHandler(handlers, TDI_EVENT_DISCONNECT, KsDisconnectEventHandler);
1488 SetEventHandler(handlers, TDI_EVENT_RECEIVE, KsTcpReceiveEventHandler);
1489 SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, KsTcpReceiveExpeditedEventHandler);
1490 SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, KsTcpChainedReceiveEventHandler);
1492 // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, KsTcpChainedReceiveExpeditedEventHandler);
1494 if (tconn->kstc_type == kstt_listener) {
1495 SetEventHandler(handlers, TDI_EVENT_CONNECT, KsConnectEventHandler);
1496 } else if (tconn->kstc_type == kstt_child) {
1500 /* set all the event callbacks */
1501 status = KsSetEventHandlers(
1502 tconn->kstc_addr.FileObject, /* Address File Object */
1503 tconn, /* Event Context */
1504 &handlers /* Event callback handlers */
1509 return cfs_error_code(status);
1515 * disable all the event handler callbacks (set to NULL)
1518 * tconn: the tdi connecton object
1521 * int: ks error code
1529 ksock_tconn_t * tconn
1532 NTSTATUS status = STATUS_SUCCESS;
1533 KS_EVENT_HANDLERS handlers;
1535 /* to make sure the address object is opened already */
1536 if (tconn->kstc_addr.FileObject == NULL) {
1540 /* initialize the handlers indictor array. for sender and listenr,
1541 there are different set of callbacks. for child, we just return. */
1543 memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
1545 SetEventHandler(handlers, TDI_EVENT_ERROR, NULL);
1546 SetEventHandler(handlers, TDI_EVENT_DISCONNECT, NULL);
1547 SetEventHandler(handlers, TDI_EVENT_RECEIVE, NULL);
1548 SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, NULL);
1549 SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, NULL);
1550 // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, NULL);
1552 if (tconn->kstc_type == kstt_listener) {
1553 SetEventHandler(handlers, TDI_EVENT_CONNECT, NULL);
1554 } else if (tconn->kstc_type == kstt_child) {
1558 /* set all the event callbacks */
1559 status = KsSetEventHandlers(
1560 tconn->kstc_addr.FileObject, /* Address File Object */
1561 tconn, /* Event Context */
1562 &handlers /* Event callback handlers */
1567 return cfs_error_code(status);
1572 * KsAcceptCompletionRoutine
1573 * Irp completion routine for TdiBuildAccept (KsConnectEventHandler)
1575 * Here system gives us a chance to check the conneciton is built
1579 * DeviceObject: the device object of the transport driver
1580 * Irp: the Irp is being completed.
1581 * Context: the context we specified when issuing the Irp
1591 KsAcceptCompletionRoutine(
1592 IN PDEVICE_OBJECT DeviceObject,
1597 ksock_tconn_t * child = (ksock_tconn_t *) Context;
1598 ksock_tconn_t * parent = child->child.kstc_parent;
1600 KsPrint((2, "KsAcceptCompletionRoutine: called at Irql: %xh\n",
1601 KeGetCurrentIrql() ));
1603 KsPrint((2, "KsAcceptCompletionRoutine: Context = %xh Status = %xh\n",
1604 Context, Irp->IoStatus.Status));
1606 LASSERT(child->kstc_type == kstt_child);
1608 spin_lock(&(child->kstc_lock));
1610 LASSERT(parent->kstc_state == ksts_listening);
1611 LASSERT(child->kstc_state == ksts_connecting);
1613 if (NT_SUCCESS(Irp->IoStatus.Status)) {
1615 child->child.kstc_accepted = TRUE;
1617 child->kstc_state = ksts_connected;
1619 /* wake up the daemon thread which waits on this event */
1621 &(parent->listener.kstc_accept_event),
1626 spin_unlock(&(child->kstc_lock));
1628 KsPrint((2, "KsAcceptCompletionRoutine: Get %xh now signal the event ...\n", parent));
1632 /* re-use this child connecton */
1633 child->child.kstc_accepted = FALSE;
1634 child->child.kstc_busy = FALSE;
1635 child->kstc_state = ksts_associated;
1637 spin_unlock(&(child->kstc_lock));
1640 /* now free the Irp */
1643 /* drop the refer count of the child */
1644 ks_put_tconn(child);
1646 return (STATUS_MORE_PROCESSING_REQUIRED);
1651 * ks_get_vacancy_backlog
1652 * Get a vacancy listeing child from the backlog list
1655 * parent: the listener daemon connection
1658 * the child listening connection or NULL in failure
1661 * Parent's lock should be acquired before calling.
1665 ks_get_vacancy_backlog(
1666 ksock_tconn_t * parent
1669 ksock_tconn_t * child;
1671 LASSERT(parent->kstc_type == kstt_listener);
1672 LASSERT(parent->kstc_state == ksts_listening);
1674 if (list_empty(&(parent->listener.kstc_listening.list))) {
1680 struct list_head * tmp;
1682 /* check the listening queue and try to get a free connecton */
1684 list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
1685 child = list_entry (tmp, ksock_tconn_t, child.kstc_link);
1686 spin_lock(&(child->kstc_lock));
1688 if (!child->child.kstc_busy) {
1689 LASSERT(child->kstc_state == ksts_associated);
1690 child->child.kstc_busy = TRUE;
1691 spin_unlock(&(child->kstc_lock));
1694 spin_unlock(&(child->kstc_lock));
1704 KsSearchIpAddress(PUNICODE_STRING DeviceName)
1706 ks_addr_slot_t * slot = NULL;
1707 PLIST_ENTRY list = NULL;
1709 spin_lock(&ks_data.ksnd_addrs_lock);
1711 list = ks_data.ksnd_addrs_list.Flink;
1712 while (list != &ks_data.ksnd_addrs_list) {
1713 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
1714 if (RtlCompareUnicodeString(
1724 spin_unlock(&ks_data.ksnd_addrs_lock);
1730 KsCleanupIpAddresses()
1732 spin_lock(&ks_data.ksnd_addrs_lock);
1734 while (!IsListEmpty(&ks_data.ksnd_addrs_list)) {
1736 ks_addr_slot_t * slot = NULL;
1737 PLIST_ENTRY list = NULL;
1739 list = RemoveHeadList(&ks_data.ksnd_addrs_list);
1740 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
1742 ks_data.ksnd_naddrs--;
1745 cfs_assert(ks_data.ksnd_naddrs == 0);
1746 spin_unlock(&ks_data.ksnd_addrs_lock);
1750 KsAddAddressHandler(
1751 IN PTA_ADDRESS Address,
1752 IN PUNICODE_STRING DeviceName,
1753 IN PTDI_PNP_CONTEXT Context
1756 PTDI_ADDRESS_IP IpAddress = NULL;
1758 if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
1759 Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
1761 ks_addr_slot_t * slot = NULL;
1763 IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
1764 KsPrint((1, "KsAddAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
1765 DeviceName, Context, IpAddress->in_addr,
1766 (IpAddress->in_addr & 0xFF000000) >> 24,
1767 (IpAddress->in_addr & 0x00FF0000) >> 16,
1768 (IpAddress->in_addr & 0x0000FF00) >> 8,
1769 (IpAddress->in_addr & 0x000000FF) >> 0 ));
1771 slot = KsSearchIpAddress(DeviceName);
1775 slot->ip_addr = ntohl(IpAddress->in_addr);
1777 slot = cfs_alloc(sizeof(ks_addr_slot_t) + DeviceName->Length, CFS_ALLOC_ZERO);
1779 spin_lock(&ks_data.ksnd_addrs_lock);
1780 InsertTailList(&ks_data.ksnd_addrs_list, &slot->link);
1781 sprintf(slot->iface, "eth%d", ks_data.ksnd_naddrs++);
1782 slot->ip_addr = ntohl(IpAddress->in_addr);
1784 RtlMoveMemory(&slot->buffer[0], DeviceName->Buffer, DeviceName->Length);
1785 slot->devname.Length = DeviceName->Length;
1786 slot->devname.MaximumLength = DeviceName->Length + sizeof(WCHAR);
1787 slot->devname.Buffer = slot->buffer;
1788 spin_unlock(&ks_data.ksnd_addrs_lock);
1795 KsDelAddressHandler(
1796 IN PTA_ADDRESS Address,
1797 IN PUNICODE_STRING DeviceName,
1798 IN PTDI_PNP_CONTEXT Context
1801 PTDI_ADDRESS_IP IpAddress = NULL;
1803 if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
1804 Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
1806 ks_addr_slot_t * slot = NULL;
1808 slot = KsSearchIpAddress(DeviceName);
1814 IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
1815 KsPrint((1, "KsDelAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
1816 DeviceName, Context, IpAddress->in_addr,
1817 (IpAddress->in_addr & 0xFF000000) >> 24,
1818 (IpAddress->in_addr & 0x00FF0000) >> 16,
1819 (IpAddress->in_addr & 0x0000FF00) >> 8,
1820 (IpAddress->in_addr & 0x000000FF) >> 0 ));
1825 KsRegisterPnpHandlers()
1827 TDI20_CLIENT_INTERFACE_INFO ClientInfo;
1829 /* initialize the global ks_data members */
1830 RtlInitUnicodeString(&ks_data.ksnd_client_name, TDILND_MODULE_NAME);
1831 spin_lock_init(&ks_data.ksnd_addrs_lock);
1832 InitializeListHead(&ks_data.ksnd_addrs_list);
1834 /* register the pnp handlers */
1835 RtlZeroMemory(&ClientInfo, sizeof(ClientInfo));
1836 ClientInfo.TdiVersion = TDI_CURRENT_VERSION;
1838 ClientInfo.ClientName = &ks_data.ksnd_client_name;
1839 ClientInfo.AddAddressHandlerV2 = KsAddAddressHandler;
1840 ClientInfo.DelAddressHandlerV2 = KsDelAddressHandler;
1842 return TdiRegisterPnPHandlers(&ClientInfo, sizeof(ClientInfo),
1843 &ks_data.ksnd_pnp_handle);
1847 KsDeregisterPnpHandlers()
1849 if (ks_data.ksnd_pnp_handle) {
1851 /* De-register the pnp handlers */
1853 TdiDeregisterPnPHandlers(ks_data.ksnd_pnp_handle);
1854 ks_data.ksnd_pnp_handle = NULL;
1856 /* cleanup all the ip address slots */
1857 KsCleanupIpAddresses();
1862 * KsConnectEventHandler
1863 * Connect event handler event handler, called by the underlying TDI
1864 * transport in response to an incoming request to the listening daemon.
1866 * it will grab a vacancy backlog from the children tconn list, and
1867 * build an acception Irp with it, then transfer the Irp to TDI driver.
1870 * TdiEventContext: the tdi connnection object of the listening daemon
1874 * Nt kernel status code
1881 KsConnectEventHandler(
1882 IN PVOID TdiEventContext,
1883 IN LONG RemoteAddressLength,
1884 IN PVOID RemoteAddress,
1885 IN LONG UserDataLength,
1887 IN LONG OptionsLength,
1889 OUT CONNECTION_CONTEXT * ConnectionContext,
1890 OUT PIRP * AcceptIrp
1893 ksock_tconn_t * parent;
1894 ksock_tconn_t * child;
1896 PFILE_OBJECT FileObject;
1897 PDEVICE_OBJECT DeviceObject;
1901 PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
1903 KsPrint((2,"KsConnectEventHandler: call at Irql: %u\n", KeGetCurrentIrql()));
1904 parent = (ksock_tconn_t *) TdiEventContext;
1906 LASSERT(parent->kstc_type == kstt_listener);
1908 spin_lock(&(parent->kstc_lock));
1910 if (parent->kstc_state == ksts_listening) {
1912 /* allocate a new ConnectionInfo to backup the peer's info */
1914 ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
1915 NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) +
1916 RemoteAddressLength, 'iCsK' );
1918 if (NULL == ConnectionInfo) {
1920 Status = STATUS_INSUFFICIENT_RESOURCES;
1921 cfs_enter_debugger();
1925 /* initializing ConnectionInfo structure ... */
1927 ConnectionInfo->UserDataLength = UserDataLength;
1928 ConnectionInfo->UserData = UserData;
1929 ConnectionInfo->OptionsLength = OptionsLength;
1930 ConnectionInfo->Options = Options;
1931 ConnectionInfo->RemoteAddressLength = RemoteAddressLength;
1932 ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
1935 ConnectionInfo->RemoteAddress,
1940 /* get the vacancy listening child tdi connections */
1942 child = ks_get_vacancy_backlog(parent);
1946 spin_lock(&(child->kstc_lock));
1947 child->child.kstc_info.ConnectionInfo = ConnectionInfo;
1948 child->child.kstc_info.Remote = ConnectionInfo->RemoteAddress;
1949 child->kstc_state = ksts_connecting;
1950 spin_unlock(&(child->kstc_lock));
1954 KsPrint((2, "KsConnectEventHandler: No enough backlogs: Refsued the connectio: %xh\n", parent));
1956 Status = STATUS_INSUFFICIENT_RESOURCES;
1961 FileObject = child->child.kstc_info.FileObject;
1962 DeviceObject = IoGetRelatedDeviceObject (FileObject);
1964 Irp = KsBuildTdiIrp(DeviceObject);
1970 KsAcceptCompletionRoutine,
1976 IoSetNextIrpStackLocation(Irp);
1978 /* grap the refer of the child tdi connection */
1979 ks_get_tconn(child);
1981 Status = STATUS_MORE_PROCESSING_REQUIRED;
1984 *ConnectionContext = child;
1988 Status = STATUS_CONNECTION_REFUSED;
1992 spin_unlock(&(parent->kstc_lock));
1998 spin_unlock(&(parent->kstc_lock));
2002 *ConnectionContext = NULL;
2004 if (ConnectionInfo) {
2006 ExFreePool(ConnectionInfo);
2019 * KsDisconnectCompletionRoutine
2020 * the Irp completion routine for TdiBuildDisconect
2022 * We just signal the event and return MORE_PRO... to
2023 * let the caller take the responsibility of the Irp.
2026 * DeviceObject: the device object of the transport
2027 * Irp: the Irp is being completed.
2028 * Context: the event specified by the caller
2038 KsDisconectCompletionRoutine (
2039 IN PDEVICE_OBJECT DeviceObject,
2045 KeSetEvent((PKEVENT) Context, 0, FALSE);
2047 return STATUS_MORE_PROCESSING_REQUIRED;
2049 UNREFERENCED_PARAMETER(DeviceObject);
2054 * KsDisconnectHelper
2055 * the routine to be executed in the WorkItem procedure
2056 * this routine is to disconnect a tdi connection
2059 * Workitem: the context transferred to the workitem
2065 * tconn is already referred in abort_connecton ...
2069 KsDisconnectHelper(PKS_DISCONNECT_WORKITEM WorkItem)
2071 ksock_tconn_t * tconn = WorkItem->tconn;
2073 DbgPrint("KsDisconnectHelper: disconnecting tconn=%p\n", tconn);
2074 ks_disconnect_tconn(tconn, WorkItem->Flags);
2076 KeSetEvent(&(WorkItem->Event), 0, FALSE);
2078 spin_lock(&(tconn->kstc_lock));
2079 cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
2080 spin_unlock(&(tconn->kstc_lock));
2081 ks_put_tconn(tconn);
2086 * KsDisconnectEventHandler
2087 * Disconnect event handler event handler, called by the underlying TDI transport
2088 * in response to an incoming disconnection notification from a remote node.
2091 * ConnectionContext: tdi connnection object
2092 * DisconnectFlags: specifies the nature of the disconnection
2096 * Nt kernel status code
2104 KsDisconnectEventHandler(
2105 IN PVOID TdiEventContext,
2106 IN CONNECTION_CONTEXT ConnectionContext,
2107 IN LONG DisconnectDataLength,
2108 IN PVOID DisconnectData,
2109 IN LONG DisconnectInformationLength,
2110 IN PVOID DisconnectInformation,
2111 IN ULONG DisconnectFlags
2114 ksock_tconn_t * tconn;
2116 PKS_DISCONNECT_WORKITEM WorkItem;
2118 tconn = (ksock_tconn_t *)ConnectionContext;
2120 KsPrint((2, "KsTcpDisconnectEventHandler: called at Irql: %xh\n",
2121 KeGetCurrentIrql() ));
2123 KsPrint((2, "tconn = %x DisconnectFlags= %xh\n",
2124 tconn, DisconnectFlags));
2126 ks_get_tconn(tconn);
2127 spin_lock(&(tconn->kstc_lock));
2129 WorkItem = &(tconn->kstc_disconnect);
2131 if (tconn->kstc_state != ksts_connected) {
2133 Status = STATUS_SUCCESS;
2137 if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_ABORT)) {
2139 Status = STATUS_REMOTE_DISCONNECT;
2141 } else if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_RELEASE)) {
2143 Status = STATUS_GRACEFUL_DISCONNECT;
2146 if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
2148 ks_get_tconn(tconn);
2150 WorkItem->Flags = DisconnectFlags;
2151 WorkItem->tconn = tconn;
2153 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
2155 /* queue the workitem to call */
2156 ExQueueWorkItem(&(WorkItem->WorkItem), DelayedWorkQueue);
2160 spin_unlock(&(tconn->kstc_lock));
2161 ks_put_tconn(tconn);
2167 KsTcpReceiveCompletionRoutine(
2169 IN PKS_TCP_COMPLETION_CONTEXT Context
2172 NTSTATUS Status = Irp->IoStatus.Status;
2174 if (NT_SUCCESS(Status)) {
2176 ksock_tconn_t *tconn = Context->tconn;
2178 PKS_TSDU_DAT KsTsduDat = Context->CompletionContext;
2179 PKS_TSDU_BUF KsTsduBuf = Context->CompletionContext;
2181 KsPrint((1, "KsTcpReceiveCompletionRoutine: Total %xh bytes.\n",
2182 Context->KsTsduMgr->TotalBytes ));
2184 spin_lock(&(tconn->kstc_lock));
2186 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
2187 if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
2188 cfs_clear_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
2190 cfs_enter_debugger();
2193 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
2194 if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
2195 cfs_clear_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
2197 cfs_enter_debugger();
2201 spin_unlock(&(tconn->kstc_lock));
2203 /* wake up the thread waiting for the completion of this Irp */
2204 KeSetEvent(Context->Event, 0, FALSE);
2206 /* re-active the ks connection and wake up the scheduler */
2207 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2208 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2209 Context->KsTsduMgr->TotalBytes );
2214 /* un-expected errors occur, we must abort the connection */
2215 ks_abort_tconn(Context->tconn);
2220 /* Freeing the Context structure... */
2221 ExFreePool(Context);
2236 * KsTcpCompletionRoutine
2237 * the Irp completion routine for TdiBuildSend and TdiBuildReceive ...
2238 * We need call the use's own CompletionRoutine if specified. Or
2239 * it's a synchronous case, we need signal the event.
2242 * DeviceObject: the device object of the transport
2243 * Irp: the Irp is being completed.
2244 * Context: the context we specified when issuing the Irp
2254 KsTcpCompletionRoutine(
2255 IN PDEVICE_OBJECT DeviceObject,
2262 PKS_TCP_COMPLETION_CONTEXT CompletionContext = NULL;
2263 ksock_tconn_t * tconn = NULL;
2265 CompletionContext = (PKS_TCP_COMPLETION_CONTEXT) Context;
2266 tconn = CompletionContext->tconn;
2268 /* release the chained mdl */
2269 KsReleaseMdl(Irp->MdlAddress, FALSE);
2270 Irp->MdlAddress = NULL;
2272 if (CompletionContext->CompletionRoutine) {
2274 if ( CompletionContext->bCounted &&
2275 InterlockedDecrement(&CompletionContext->ReferCount) != 0 ) {
2280 // Giving control to user specified CompletionRoutine ...
2283 CompletionContext->CompletionRoutine(
2291 // Signaling the Event ...
2294 KeSetEvent(CompletionContext->Event, 0, FALSE);
2297 /* drop the reference count of the tconn object */
2298 ks_put_tconn(tconn);
2302 cfs_enter_debugger();
2307 return STATUS_MORE_PROCESSING_REQUIRED;
2311 * KsTcpSendCompletionRoutine
2312 * the user specified Irp completion routine for asynchronous
2313 * data transmission requests.
2315 * It will do th cleanup job of the ksock_tx_t and wake up the
2316 * ks scheduler thread
2319 * Irp: the Irp is being completed.
2320 * Context: the context we specified when issuing the Irp
2330 KsTcpSendCompletionRoutine(
2332 IN PKS_TCP_COMPLETION_CONTEXT Context
2335 NTSTATUS Status = Irp->IoStatus.Status;
2336 ULONG rc = Irp->IoStatus.Information;
2337 ksock_tconn_t * tconn = Context->tconn;
2338 PKS_TSDUMGR KsTsduMgr = Context->KsTsduMgr;
2344 if (NT_SUCCESS(Status)) {
2346 if (Context->bCounted) {
2347 PVOID tx = Context->CompletionContext;
2349 ASSERT(tconn->kstc_update_tx != NULL);
2351 /* update the tx, rebasing the kiov or iov pointers */
2352 tx = tconn->kstc_update_tx(tconn, tx, rc);
2354 /* update the KsTsudMgr total bytes */
2355 spin_lock(&tconn->kstc_lock);
2356 KsTsduMgr->TotalBytes -= rc;
2357 spin_unlock(&tconn->kstc_lock);
2360 * now it's time to re-queue the conns into the
2361 * scheduler queue and wake the scheduler thread.
2364 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2365 tconn->kstc_sched_cb( tconn, TRUE, tx, 0);
2370 PKS_TSDU KsTsdu = Context->CompletionContext;
2371 PKS_TSDU_BUF KsTsduBuf = Context->CompletionContext2;
2372 PKS_TSDU_DAT KsTsduDat = Context->CompletionContext2;
2374 spin_lock(&tconn->kstc_lock);
2375 /* This is bufferred sending ... */
2376 ASSERT(KsTsduBuf->StartOffset == 0);
2378 if (KsTsduBuf->DataLength > Irp->IoStatus.Information) {
2379 /* not fully sent .... we have to abort the connection */
2380 spin_unlock(&tconn->kstc_lock);
2381 ks_abort_tconn(tconn);
2385 if (KsTsduBuf->TsduType == TSDU_TYPE_BUF) {
2386 /* free the buffer */
2387 ExFreePool(KsTsduBuf->UserBuffer);
2388 KsTsduMgr->TotalBytes -= KsTsduBuf->DataLength;
2389 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
2390 } else if (KsTsduDat->TsduType == TSDU_TYPE_DAT) {
2391 KsTsduMgr->TotalBytes -= KsTsduDat->DataLength;
2392 KsTsdu->StartOffset += KsTsduDat->TotalLength;
2394 cfs_enter_debugger(); /* shoult not get here */
2397 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
2399 list_del(&KsTsdu->Link);
2400 KsTsduMgr->NumOfTsdu--;
2401 KsPutKsTsdu(KsTsdu);
2404 spin_unlock(&tconn->kstc_lock);
2409 /* cfs_enter_debugger(); */
2412 * for the case that the transmission is ussuccessful,
2413 * we need abort the tdi connection, but not destroy it.
2414 * the socknal conn will drop the refer count, then the
2415 * tdi connection will be freed.
2418 ks_abort_tconn(tconn);
2423 /* freeing the Context structure... */
2426 ExFreePool(Context);
2430 /* it's our duty to free the Irp. */
2443 * Normal receive event handler
2445 * It will move data from system Tsdu to our TsduList
2449 KsTcpReceiveEventHandler(
2450 IN PVOID TdiEventContext,
2451 IN CONNECTION_CONTEXT ConnectionContext,
2452 IN ULONG ReceiveFlags,
2453 IN ULONG BytesIndicated,
2454 IN ULONG BytesAvailable,
2455 OUT ULONG * BytesTaken,
2457 OUT PIRP * IoRequestPacket
2462 ksock_tconn_t * tconn;
2465 PKS_TSDUMGR KsTsduMgr;
2467 PKS_TSDU_DAT KsTsduDat;
2468 PKS_TSDU_BUF KsTsduBuf;
2470 BOOLEAN bIsExpedited;
2471 BOOLEAN bIsCompleteTsdu;
2473 BOOLEAN bNewTsdu = FALSE;
2474 BOOLEAN bNewBuff = FALSE;
2476 PCHAR Buffer = NULL;
2480 PFILE_OBJECT FileObject;
2481 PDEVICE_OBJECT DeviceObject;
2483 ULONG BytesReceived = 0;
2485 PKS_TCP_COMPLETION_CONTEXT context = NULL;
2488 tconn = (ksock_tconn_t *) ConnectionContext;
2490 ks_get_tconn(tconn);
2492 /* check whether the whole body of payload is received or not */
2493 if ( (cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_ENTIRE_MESSAGE)) &&
2494 (BytesIndicated == BytesAvailable) ) {
2495 bIsCompleteTsdu = TRUE;
2497 bIsCompleteTsdu = FALSE;
2500 bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
2502 KsPrint((2, "KsTcpReceiveEventHandler BytesIndicated = %d BytesAvailable = %d ...\n", BytesIndicated, BytesAvailable));
2503 KsPrint((2, "bIsCompleteTsdu = %d bIsExpedited = %d\n", bIsCompleteTsdu, bIsExpedited ));
2505 spin_lock(&(tconn->kstc_lock));
2507 /* check whether we are conntected or not listener ¡Â*/
2508 if ( !((tconn->kstc_state == ksts_connected) &&
2509 (tconn->kstc_type == kstt_sender ||
2510 tconn->kstc_type == kstt_child))) {
2512 *BytesTaken = BytesIndicated;
2514 spin_unlock(&(tconn->kstc_lock));
2515 ks_put_tconn(tconn);
2517 return (STATUS_SUCCESS);
2520 if (tconn->kstc_type == kstt_sender) {
2521 KsChain = &(tconn->sender.kstc_recv);
2523 LASSERT(tconn->kstc_type == kstt_child);
2524 KsChain = &(tconn->child.kstc_recv);
2528 KsTsduMgr = &(KsChain->Expedited);
2530 KsTsduMgr = &(KsChain->Normal);
2533 /* if the Tsdu is even larger than the biggest Tsdu, we have
2534 to allocate new buffer and use TSDU_TYOE_BUF to store it */
2536 if ( KS_TSDU_STRU_SIZE(BytesAvailable) > ks_data.ksnd_tsdu_size -
2537 KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
2541 /* retrieve the latest Tsdu buffer form TsduMgr
2542 list if the list is not empty. */
2544 if (list_empty(&(KsTsduMgr->TsduList))) {
2546 LASSERT(KsTsduMgr->NumOfTsdu == 0);
2551 LASSERT(KsTsduMgr->NumOfTsdu > 0);
2552 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
2554 /* if this Tsdu does not contain enough space, we need
2555 allocate a new Tsdu queue. */
2558 if ( KsTsdu->LastOffset + sizeof(KS_TSDU_BUF) >
2559 KsTsdu->TotalLength ) {
2563 if ( KS_TSDU_STRU_SIZE(BytesAvailable) >
2564 KsTsdu->TotalLength - KsTsdu->LastOffset ) {
2570 /* allocating the buffer for TSDU_TYPE_BUF */
2572 Buffer = ExAllocatePool(NonPagedPool, BytesAvailable);
2573 if (NULL == Buffer) {
2574 /* there's no enough memory for us. We just try to
2575 receive maximum bytes with a new Tsdu */
2581 /* allocate a new Tsdu in case we are not statisfied. */
2583 if (NULL == KsTsdu) {
2585 KsTsdu = KsAllocateKsTsdu();
2587 if (NULL == KsTsdu) {
2594 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2595 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2599 /* setup up the KS_TSDU_BUF record */
2601 KsTsduBuf->TsduType = TSDU_TYPE_BUF;
2602 KsTsduBuf->TsduFlags = 0;
2603 KsTsduBuf->StartOffset = 0;
2604 KsTsduBuf->UserBuffer = Buffer;
2605 KsTsduBuf->DataLength = BytesReceived = BytesAvailable;
2607 KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
2611 /* setup the KS_TSDU_DATA to contain all the messages */
2613 KsTsduDat->TsduType = TSDU_TYPE_DAT;
2614 KsTsduDat->TsduFlags = 0;
2616 if ( KsTsdu->TotalLength - KsTsdu->LastOffset >=
2617 KS_TSDU_STRU_SIZE(BytesAvailable) ) {
2618 BytesReceived = BytesAvailable;
2620 BytesReceived = KsTsdu->TotalLength - KsTsdu->LastOffset -
2621 FIELD_OFFSET(KS_TSDU_DAT, Data);
2622 BytesReceived &= (~((ULONG)3));
2624 KsTsduDat->DataLength = BytesReceived;
2625 KsTsduDat->TotalLength = KS_TSDU_STRU_SIZE(BytesReceived);
2626 KsTsduDat->StartOffset = 0;
2628 Buffer = &KsTsduDat->Data[0];
2630 KsTsdu->LastOffset += KsTsduDat->TotalLength;
2633 KsTsduMgr->TotalBytes += BytesReceived;
2635 if (bIsCompleteTsdu) {
2637 /* It's a complete receive, we just move all
2638 the data from system to our Tsdu */
2646 *BytesTaken = BytesReceived;
2647 Status = STATUS_SUCCESS;
2650 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2651 KsTsduMgr->NumOfTsdu++;
2654 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
2656 /* re-active the ks connection and wake up the scheduler */
2657 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2658 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2659 KsTsduMgr->TotalBytes );
2664 /* there's still data in tdi internal queue, we need issue a new
2665 Irp to receive all of them. first allocate the tcp context */
2667 context = ExAllocatePoolWithTag(
2669 sizeof(KS_TCP_COMPLETION_CONTEXT),
2674 Status = STATUS_INSUFFICIENT_RESOURCES;
2678 /* setup the context */
2679 RtlZeroMemory(context, sizeof(KS_TCP_COMPLETION_CONTEXT));
2681 context->tconn = tconn;
2682 context->CompletionRoutine = KsTcpReceiveCompletionRoutine;
2683 context->CompletionContext = KsTsdu;
2684 context->CompletionContext = bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat;
2685 context->KsTsduMgr = KsTsduMgr;
2686 context->Event = &(KsTsduMgr->Event);
2688 if (tconn->kstc_type == kstt_sender) {
2689 FileObject = tconn->sender.kstc_info.FileObject;
2691 FileObject = tconn->child.kstc_info.FileObject;
2694 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2696 /* build new tdi Irp and setup it. */
2697 Irp = KsBuildTdiIrp(DeviceObject);
2703 Status = KsLockUserBuffer(
2711 if (!NT_SUCCESS(Status)) {
2719 KsTcpCompletionRoutine,
2722 ReceiveFlags & (TDI_RECEIVE_NORMAL | TDI_RECEIVE_EXPEDITED),
2726 IoSetNextIrpStackLocation(Irp);
2728 /* return the newly built Irp to transport driver,
2729 it will process it to receive all the data */
2731 *IoRequestPacket = Irp;
2736 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2737 KsTsduMgr->NumOfTsdu++;
2741 cfs_set_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
2743 cfs_set_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
2745 ks_get_tconn(tconn);
2746 Status = STATUS_MORE_PROCESSING_REQUIRED;
2749 spin_unlock(&(tconn->kstc_lock));
2750 ks_put_tconn(tconn);
2756 spin_unlock(&(tconn->kstc_lock));
2758 if (bNewTsdu && (KsTsdu != NULL)) {
2759 KsFreeKsTsdu(KsTsdu);
2763 KsReleaseMdl(Mdl, FALSE);
2771 ExFreePool(context);
2774 ks_abort_tconn(tconn);
2775 ks_put_tconn(tconn);
2777 *BytesTaken = BytesAvailable;
2778 Status = STATUS_SUCCESS;
2784 * Expedited receive event handler
2788 KsTcpReceiveExpeditedEventHandler(
2789 IN PVOID TdiEventContext,
2790 IN CONNECTION_CONTEXT ConnectionContext,
2791 IN ULONG ReceiveFlags,
2792 IN ULONG BytesIndicated,
2793 IN ULONG BytesAvailable,
2794 OUT ULONG * BytesTaken,
2796 OUT PIRP * IoRequestPacket
2799 return KsTcpReceiveEventHandler(
2802 ReceiveFlags | TDI_RECEIVE_EXPEDITED,
2813 * Bulk receive event handler
2815 * It will queue all the system Tsdus to our TsduList.
2816 * Then later ks_recv_mdl will release them.
2820 KsTcpChainedReceiveEventHandler (
2821 IN PVOID TdiEventContext, // the event context
2822 IN CONNECTION_CONTEXT ConnectionContext,
2823 IN ULONG ReceiveFlags,
2824 IN ULONG ReceiveLength,
2825 IN ULONG StartingOffset, // offset of start of client data in TSDU
2826 IN PMDL Tsdu, // TSDU data chain
2827 IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives
2833 ksock_tconn_t * tconn;
2836 PKS_TSDUMGR KsTsduMgr;
2838 PKS_TSDU_MDL KsTsduMdl;
2840 BOOLEAN bIsExpedited;
2841 BOOLEAN bNewTsdu = FALSE;
2843 tconn = (ksock_tconn_t *) ConnectionContext;
2845 bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
2847 KsPrint((2, "KsTcpChainedReceive: ReceiveLength = %xh bIsExpedited = %d\n", ReceiveLength, bIsExpedited));
2849 ks_get_tconn(tconn);
2850 spin_lock(&(tconn->kstc_lock));
2852 /* check whether we are conntected or not listener ¡Â*/
2853 if ( !((tconn->kstc_state == ksts_connected) &&
2854 (tconn->kstc_type == kstt_sender ||
2855 tconn->kstc_type == kstt_child))) {
2857 spin_unlock(&(tconn->kstc_lock));
2858 ks_put_tconn(tconn);
2860 return (STATUS_SUCCESS);
2863 /* get the latest Tsdu buffer form TsduMgr list.
2864 just set NULL if the list is empty. */
2866 if (tconn->kstc_type == kstt_sender) {
2867 KsChain = &(tconn->sender.kstc_recv);
2869 LASSERT(tconn->kstc_type == kstt_child);
2870 KsChain = &(tconn->child.kstc_recv);
2874 KsTsduMgr = &(KsChain->Expedited);
2876 KsTsduMgr = &(KsChain->Normal);
2879 if (list_empty(&(KsTsduMgr->TsduList))) {
2881 LASSERT(KsTsduMgr->NumOfTsdu == 0);
2886 LASSERT(KsTsduMgr->NumOfTsdu > 0);
2887 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
2888 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
2890 if (sizeof(KS_TSDU_MDL) > KsTsdu->TotalLength - KsTsdu->LastOffset) {
2895 /* if there's no Tsdu or the free size is not enough for this
2896 KS_TSDU_MDL structure. We need re-allocate a new Tsdu. */
2898 if (NULL == KsTsdu) {
2900 KsTsdu = KsAllocateKsTsdu();
2902 if (NULL == KsTsdu) {
2909 /* just queue the KS_TSDU_MDL to the Tsdu buffer */
2911 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2913 KsTsduMdl->TsduType = TSDU_TYPE_MDL;
2914 KsTsduMdl->DataLength = ReceiveLength;
2915 KsTsduMdl->StartOffset = StartingOffset;
2916 KsTsduMdl->Mdl = Tsdu;
2917 KsTsduMdl->Descriptor = TsduDescriptor;
2919 KsTsdu->LastOffset += sizeof(KS_TSDU_MDL);
2920 KsTsduMgr->TotalBytes += ReceiveLength;
2922 KsPrint((2, "KsTcpChainedReceiveEventHandler: Total %xh bytes.\n",
2923 KsTsduMgr->TotalBytes ));
2925 Status = STATUS_PENDING;
2927 /* attach it to the TsduMgr list if the Tsdu is newly created. */
2930 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2931 KsTsduMgr->NumOfTsdu++;
2934 spin_unlock(&(tconn->kstc_lock));
2936 /* wake up the threads waiing in ks_recv_mdl */
2937 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
2939 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2940 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2941 KsTsduMgr->TotalBytes );
2944 ks_put_tconn(tconn);
2946 /* Return STATUS_PENDING to system because we are still
2947 owning the MDL resources. ks_recv_mdl is expected
2948 to free the MDL resources. */
2954 spin_unlock(&(tconn->kstc_lock));
2956 if (bNewTsdu && (KsTsdu != NULL)) {
2957 KsFreeKsTsdu(KsTsdu);
2960 /* abort the tdi connection */
2961 ks_abort_tconn(tconn);
2962 ks_put_tconn(tconn);
2965 Status = STATUS_SUCCESS;
2972 * Expedited & Bulk receive event handler
2976 KsTcpChainedReceiveExpeditedEventHandler (
2977 IN PVOID TdiEventContext, // the event context
2978 IN CONNECTION_CONTEXT ConnectionContext,
2979 IN ULONG ReceiveFlags,
2980 IN ULONG ReceiveLength,
2981 IN ULONG StartingOffset, // offset of start of client data in TSDU
2982 IN PMDL Tsdu, // TSDU data chain
2983 IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives
2986 return KsTcpChainedReceiveEventHandler(
2989 ReceiveFlags | TDI_RECEIVE_EXPEDITED,
2998 KsPrintProviderInfo(
3000 PTDI_PROVIDER_INFO ProviderInfo
3003 KsPrint((2, "%ws ProviderInfo:\n", DeviceName));
3005 KsPrint((2, " Version : 0x%4.4X\n", ProviderInfo->Version ));
3006 KsPrint((2, " MaxSendSize : %d\n", ProviderInfo->MaxSendSize ));
3007 KsPrint((2, " MaxConnectionUserData: %d\n", ProviderInfo->MaxConnectionUserData ));
3008 KsPrint((2, " MaxDatagramSize : %d\n", ProviderInfo->MaxDatagramSize ));
3009 KsPrint((2, " ServiceFlags : 0x%8.8X\n", ProviderInfo->ServiceFlags ));
3011 if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTION_MODE) {
3012 KsPrint((2, " CONNECTION_MODE\n"));
3015 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ORDERLY_RELEASE) {
3016 KsPrint((2, " ORDERLY_RELEASE\n"));
3019 if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTIONLESS_MODE) {
3020 KsPrint((2, " CONNECTIONLESS_MODE\n"));
3023 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ERROR_FREE_DELIVERY) {
3024 KsPrint((2, " ERROR_FREE_DELIVERY\n"));
3027 if( ProviderInfo->ServiceFlags & TDI_SERVICE_SECURITY_LEVEL ) {
3028 KsPrint((2, " SECURITY_LEVEL\n"));
3031 if (ProviderInfo->ServiceFlags & TDI_SERVICE_BROADCAST_SUPPORTED) {
3032 KsPrint((2, " BROADCAST_SUPPORTED\n"));
3035 if (ProviderInfo->ServiceFlags & TDI_SERVICE_MULTICAST_SUPPORTED) {
3036 KsPrint((2, " MULTICAST_SUPPORTED\n"));
3039 if (ProviderInfo->ServiceFlags & TDI_SERVICE_DELAYED_ACCEPTANCE) {
3040 KsPrint((2, " DELAYED_ACCEPTANCE\n"));
3043 if (ProviderInfo->ServiceFlags & TDI_SERVICE_EXPEDITED_DATA) {
3044 KsPrint((2, " EXPEDITED_DATA\n"));
3047 if( ProviderInfo->ServiceFlags & TDI_SERVICE_INTERNAL_BUFFERING) {
3048 KsPrint((2, " INTERNAL_BUFFERING\n"));
3051 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ROUTE_DIRECTED) {
3052 KsPrint((2, " ROUTE_DIRECTED\n"));
3055 if (ProviderInfo->ServiceFlags & TDI_SERVICE_NO_ZERO_LENGTH) {
3056 KsPrint((2, " NO_ZERO_LENGTH\n"));
3059 if (ProviderInfo->ServiceFlags & TDI_SERVICE_POINT_TO_POINT) {
3060 KsPrint((2, " POINT_TO_POINT\n"));
3063 if (ProviderInfo->ServiceFlags & TDI_SERVICE_MESSAGE_MODE) {
3064 KsPrint((2, " MESSAGE_MODE\n"));
3067 if (ProviderInfo->ServiceFlags & TDI_SERVICE_HALF_DUPLEX) {
3068 KsPrint((2, " HALF_DUPLEX\n"));
3071 KsPrint((2, " MinimumLookaheadData : %d\n", ProviderInfo->MinimumLookaheadData ));
3072 KsPrint((2, " MaximumLookaheadData : %d\n", ProviderInfo->MaximumLookaheadData ));
3073 KsPrint((2, " NumberOfResources : %d\n", ProviderInfo->NumberOfResources ));
3079 * Reuse a Tsdu from the freelist or allocate a new Tsdu
3080 * from the LookAsideList table or the NonPagedPool
3086 * PKS_Tsdu: the new Tsdu or NULL if it fails
3095 PKS_TSDU KsTsdu = NULL;
3097 spin_lock(&(ks_data.ksnd_tsdu_lock));
3099 if (!list_empty (&(ks_data.ksnd_freetsdus))) {
3101 LASSERT(ks_data.ksnd_nfreetsdus > 0);
3103 KsTsdu = list_entry(ks_data.ksnd_freetsdus.next, KS_TSDU, Link);
3104 list_del(&(KsTsdu->Link));
3105 ks_data.ksnd_nfreetsdus--;
3109 KsTsdu = (PKS_TSDU) cfs_mem_cache_alloc(
3110 ks_data.ksnd_tsdu_slab, 0);
3113 spin_unlock(&(ks_data.ksnd_tsdu_lock));
3115 if (NULL != KsTsdu) {
3116 KsInitializeKsTsdu(KsTsdu, ks_data.ksnd_tsdu_size);
3125 * Move the Tsdu to the free tsdu list in ks_data.
3128 * KsTsdu: Tsdu to be moved.
3142 spin_lock(&(ks_data.ksnd_tsdu_lock));
3144 list_add_tail( &(KsTsdu->Link), &(ks_data.ksnd_freetsdus));
3145 ks_data.ksnd_nfreetsdus++;
3147 spin_unlock(&(ks_data.ksnd_tsdu_lock));
3153 * Release a Tsdu: uninitialize then free it.
3156 * KsTsdu: Tsdu to be freed.
3171 ks_data.ksnd_tsdu_slab,
3177 * KsInitializeKsTsdu
3178 * Initialize the Tsdu buffer header
3181 * KsTsdu: the Tsdu to be initialized
3182 * Length: the total length of the Tsdu
3197 RtlZeroMemory(KsTsdu, Length);
3198 KsTsdu->Magic = KS_TSDU_MAGIC;
3199 KsTsdu->TotalLength = Length;
3200 KsTsdu->StartOffset = KsTsdu->LastOffset =
3201 KS_DWORD_ALIGN(sizeof(KS_TSDU));
3206 * KsInitializeKsTsduMgr
3207 * Initialize the management structure of
3211 * TsduMgr: the TsduMgr to be initialized
3221 KsInitializeKsTsduMgr(
3232 &(TsduMgr->TsduList)
3235 TsduMgr->NumOfTsdu = 0;
3236 TsduMgr->TotalBytes = 0;
3241 * KsInitializeKsChain
3242 * Initialize the China structure for receiving
3246 * KsChain: the KsChain to be initialized
3256 KsInitializeKsChain(
3260 KsInitializeKsTsduMgr(&(KsChain->Normal));
3261 KsInitializeKsTsduMgr(&(KsChain->Expedited));
3267 * Clean up all the Tsdus in the TsduMgr list
3270 * KsTsduMgr: the Tsdu list manager
3273 * NTSTATUS: nt status code
3281 PKS_TSDUMGR KsTsduMgr
3285 PKS_TSDU_DAT KsTsduDat;
3286 PKS_TSDU_BUF KsTsduBuf;
3287 PKS_TSDU_MDL KsTsduMdl;
3289 LASSERT(NULL != KsTsduMgr);
3291 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
3293 while (!list_empty(&KsTsduMgr->TsduList)) {
3295 KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
3296 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
3298 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
3301 // KsTsdu is empty now, we need free it ...
3304 list_del(&(KsTsdu->Link));
3305 KsTsduMgr->NumOfTsdu--;
3307 KsFreeKsTsdu(KsTsdu);
3311 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3312 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3313 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3315 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
3317 KsTsdu->StartOffset += KsTsduDat->TotalLength;
3319 } else if (TSDU_TYPE_BUF == KsTsduBuf->TsduType) {
3321 ASSERT(KsTsduBuf->UserBuffer != NULL);
3323 if (KsTsduBuf->DataLength > KsTsduBuf->StartOffset) {
3324 ExFreePool(KsTsduBuf->UserBuffer);
3326 cfs_enter_debugger();
3329 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
3331 } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
3334 // MDL Tsdu Unit ...
3337 TdiReturnChainedReceives(
3338 &(KsTsduMdl->Descriptor),
3341 KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
3346 return STATUS_SUCCESS;
3352 * Clean up the TsduMgrs of the KsChain
3355 * KsChain: the chain managing TsduMgr
3358 * NTSTATUS: nt status code
3371 LASSERT(NULL != KsChain);
3373 Status = KsCleanupTsduMgr(
3377 if (!NT_SUCCESS(Status)) {
3378 cfs_enter_debugger();
3382 Status = KsCleanupTsduMgr(
3383 &(KsChain->Expedited)
3386 if (!NT_SUCCESS(Status)) {
3387 cfs_enter_debugger();
3399 * Clean up all the Tsdus of a tdi connected object
3402 * tconn: the tdi connection which is connected already.
3413 ksock_tconn_t * tconn
3416 NTSTATUS Status = STATUS_SUCCESS;
3419 if (tconn->kstc_type != kstt_sender &&
3420 tconn->kstc_type != kstt_child ) {
3425 if (tconn->kstc_type == kstt_sender) {
3427 Status = KsCleanupKsChain(
3428 &(tconn->sender.kstc_recv)
3431 if (!NT_SUCCESS(Status)) {
3432 cfs_enter_debugger();
3436 Status = KsCleanupKsChain(
3437 &(tconn->sender.kstc_send)
3440 if (!NT_SUCCESS(Status)) {
3441 cfs_enter_debugger();
3447 Status = KsCleanupKsChain(
3448 &(tconn->child.kstc_recv)
3451 if (!NT_SUCCESS(Status)) {
3452 cfs_enter_debugger();
3456 Status = KsCleanupKsChain(
3457 &(tconn->child.kstc_send)
3460 if (!NT_SUCCESS(Status)) {
3461 cfs_enter_debugger();
3474 * KsCopyMdlChainToMdlChain
3475 * Copy data from a [chained] Mdl to anther [chained] Mdl.
3476 * Tdi library does not provide this function. We have to
3477 * realize it ourselives.
3480 * SourceMdlChain: the source mdl
3481 * SourceOffset: start offset of the source
3482 * DestinationMdlChain: the dst mdl
3483 * DestinationOffset: the offset where data are to be copied.
3484 * BytesTobecopied: the expteced bytes to be copied
3485 * BytesCopied: to store the really copied data length
3488 * NTSTATUS: STATUS_SUCCESS or other error code
3491 * The length of source mdl must be >= SourceOffset + BytesTobecopied
3495 KsCopyMdlChainToMdlChain(
3496 IN PMDL SourceMdlChain,
3497 IN ULONG SourceOffset,
3498 IN PMDL DestinationMdlChain,
3499 IN ULONG DestinationOffset,
3500 IN ULONG BytesTobecopied,
3501 OUT PULONG BytesCopied
3504 PMDL SrcMdl = SourceMdlChain;
3505 PMDL DstMdl = DestinationMdlChain;
3507 PUCHAR SrcBuf = NULL;
3508 PUCHAR DstBuf = NULL;
3512 NTSTATUS Status = STATUS_SUCCESS;
3515 while (dwBytes < BytesTobecopied) {
3519 while (MmGetMdlByteCount(SrcMdl) <= SourceOffset) {
3521 SourceOffset -= MmGetMdlByteCount(SrcMdl);
3523 SrcMdl = SrcMdl->Next;
3525 if (NULL == SrcMdl) {
3527 Status = STATUS_INVALID_PARAMETER;
3532 while (MmGetMdlByteCount(DstMdl) <= DestinationOffset) {
3534 DestinationOffset -= MmGetMdlByteCount(DstMdl);
3536 DstMdl = DstMdl->Next;
3538 if (NULL == DstMdl) {
3540 Status = STATUS_INVALID_PARAMETER;
3545 DstBuf = (PUCHAR)KsMapMdlBuffer(DstMdl);
3547 if ((NULL == DstBuf)) {
3548 Status = STATUS_INSUFFICIENT_RESOURCES;
3553 // Here we need skip the OVERFLOW case via RtlCopyMemory :-(
3556 if ( KsQueryMdlsSize(SrcMdl) - SourceOffset >
3557 MmGetMdlByteCount(DstMdl) - DestinationOffset ) {
3559 Length = BytesTobecopied - dwBytes;
3561 if (Length > KsQueryMdlsSize(SrcMdl) - SourceOffset) {
3562 Length = KsQueryMdlsSize(SrcMdl) - SourceOffset;
3565 if (Length > MmGetMdlByteCount(DstMdl) - DestinationOffset) {
3566 Length = MmGetMdlByteCount(DstMdl) - DestinationOffset;
3569 SrcBuf = (PUCHAR)KsMapMdlBuffer(SrcMdl);
3571 if ((NULL == DstBuf)) {
3572 Status = STATUS_INSUFFICIENT_RESOURCES;
3577 DstBuf + DestinationOffset,
3578 SrcBuf + SourceOffset,
3584 Status = TdiCopyMdlToBuffer(
3589 MmGetMdlByteCount(DstMdl),
3593 if (STATUS_BUFFER_OVERFLOW == Status) {
3594 cfs_enter_debugger();
3595 } else if (!NT_SUCCESS(Status)) {
3596 cfs_enter_debugger();
3601 SourceOffset += Length;
3602 DestinationOffset += Length;
3608 if (NT_SUCCESS(Status)) {
3609 *BytesCopied = dwBytes;
3621 * Query the whole size of a MDL (may be chained)
3624 * Mdl: the Mdl to be queried
3627 * ULONG: the total size of the mdl
3634 KsQueryMdlsSize (PMDL Mdl)
3641 // Walking the MDL Chain ...
3645 Length += MmGetMdlByteCount(Next);
3655 * Allocate MDL for the buffer and lock the pages into
3659 * UserBuffer: the user buffer to be locked
3660 * Length: length in bytes of the buffer
3661 * Operation: read or write access
3662 * pMdl: the result of the created mdl
3665 * NTSTATUS: kernel status code (STATUS_SUCCESS
3666 * or other error code)
3674 IN PVOID UserBuffer,
3677 IN LOCK_OPERATION Operation,
3684 LASSERT(UserBuffer != NULL);
3688 Mdl = IoAllocateMdl(
3698 Status = STATUS_INSUFFICIENT_RESOURCES;
3705 MmProbeAndLockPages(
3711 MmBuildMdlForNonPagedPool(
3716 Status = STATUS_SUCCESS;
3720 } __except (EXCEPTION_EXECUTE_HANDLER) {
3726 cfs_enter_debugger();
3728 Status = STATUS_INVALID_USER_BUFFER;
3737 * Map the mdl into a buffer in kernel space
3740 * Mdl: the mdl to be mapped
3743 * PVOID: the buffer mapped or NULL in failure
3750 KsMapMdlBuffer (PMDL Mdl)
3752 LASSERT(Mdl != NULL);
3754 return MmGetSystemAddressForMdlSafe(
3763 * Unlock all the pages in the mdl
3766 * Mdl: memory description list to be released
3776 KsReleaseMdl (IN PMDL Mdl,
3779 LASSERT(Mdl != NULL);
3800 * allocate MDL for the user spepcified buffer and lock (paging-in)
3801 * all the pages of the buffer into system memory
3804 * buffer: the user buffer to be locked
3805 * length: length in bytes of the buffer
3806 * access: read or write access
3807 * mdl: the result of the created mdl
3810 * int: the ks error code: 0: success / -x: failture
3821 LOCK_OPERATION access,
3827 status = KsLockUserBuffer(
3835 return cfs_error_code(status);
3841 * Map the mdl pages into kernel space
3844 * mdl: the mdl to be mapped
3847 * void *: the buffer mapped or NULL in failure
3854 ks_map_mdl (ksock_mdl_t * mdl)
3856 LASSERT(mdl != NULL);
3858 return KsMapMdlBuffer(mdl);
3863 * Unlock all the pages in the mdl and release the mdl
3866 * mdl: memory description list to be released
3876 ks_release_mdl (ksock_mdl_t *mdl, int paged)
3878 LASSERT(mdl != NULL);
3880 KsReleaseMdl(mdl, paged);
3886 * allocate a new tconn structure from the SLAB cache or
3887 * NonPaged sysetm pool
3893 * ksock_tconn_t *: the address of tconn or NULL if it fails
3902 ksock_tconn_t * tconn = NULL;
3904 /* allocate ksoc_tconn_t from the slab cache memory */
3906 tconn = (ksock_tconn_t *)cfs_mem_cache_alloc(
3907 ks_data.ksnd_tconn_slab, CFS_ALLOC_ZERO);
3911 /* zero tconn elements */
3912 memset(tconn, 0, sizeof(ksock_tconn_t));
3914 /* initialize the tconn ... */
3915 tconn->kstc_magic = KS_TCONN_MAGIC;
3917 ExInitializeWorkItem(
3918 &(tconn->kstc_disconnect.WorkItem),
3920 &(tconn->kstc_disconnect)
3924 &(tconn->kstc_disconnect.Event),
3925 SynchronizationEvent,
3928 ExInitializeWorkItem(
3929 &(tconn->kstc_destroy),
3934 spin_lock_init(&(tconn->kstc_lock));
3936 ks_get_tconn(tconn);
3938 spin_lock(&(ks_data.ksnd_tconn_lock));
3940 /* attach it into global list in ks_data */
3942 list_add(&(tconn->kstc_list), &(ks_data.ksnd_tconns));
3943 ks_data.ksnd_ntconns++;
3944 spin_unlock(&(ks_data.ksnd_tconn_lock));
3946 tconn->kstc_rcv_wnd = tconn->kstc_snd_wnd = 0x10000;
3955 * free the tconn structure to the SLAB cache or NonPaged
3959 * tconn: the tcon is to be freed
3969 ks_free_tconn(ksock_tconn_t * tconn)
3971 LASSERT(atomic_read(&(tconn->kstc_refcount)) == 0);
3973 spin_lock(&(ks_data.ksnd_tconn_lock));
3975 /* remove it from the global list */
3976 list_del(&tconn->kstc_list);
3977 ks_data.ksnd_ntconns--;
3979 /* if this is the last tconn, it would be safe for
3980 ks_tdi_fini_data to quit ... */
3981 if (ks_data.ksnd_ntconns == 0) {
3982 cfs_wake_event(&ks_data.ksnd_tconn_exit);
3984 spin_unlock(&(ks_data.ksnd_tconn_lock));
3986 /* free the structure memory */
3987 cfs_mem_cache_free(ks_data.ksnd_tconn_slab, tconn);
3993 * Initialize the tconn as a listener (daemon)
3996 * tconn: the listener tconn
4007 ksock_tconn_t * tconn
4010 /* preparation: intialize the tconn members */
4012 tconn->kstc_type = kstt_listener;
4014 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4016 CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_listening.list));
4017 CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_accepted.list));
4019 cfs_init_event( &(tconn->listener.kstc_accept_event),
4023 cfs_init_event( &(tconn->listener.kstc_destroy_event),
4027 tconn->kstc_state = ksts_inited;
4033 * Initialize the tconn as a sender
4036 * tconn: the sender tconn
4047 ksock_tconn_t * tconn
4050 tconn->kstc_type = kstt_sender;
4051 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4053 KsInitializeKsChain(&(tconn->sender.kstc_recv));
4054 KsInitializeKsChain(&(tconn->sender.kstc_send));
4056 tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4057 tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4059 tconn->kstc_state = ksts_inited;
4064 * Initialize the tconn as a child
4067 * tconn: the child tconn
4078 ksock_tconn_t * tconn
4081 tconn->kstc_type = kstt_child;
4082 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4084 KsInitializeKsChain(&(tconn->child.kstc_recv));
4085 KsInitializeKsChain(&(tconn->child.kstc_send));
4087 tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4088 tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4090 tconn->kstc_state = ksts_inited;
4095 * increase the reference count of the tconn with 1
4098 * tconn: the tdi connection to be referred
4109 ksock_tconn_t * tconn
4112 atomic_inc(&(tconn->kstc_refcount));
4117 * decrease the reference count of the tconn and destroy
4118 * it if the refercount becomes 0.
4121 * tconn: the tdi connection to be dereferred
4132 ksock_tconn_t *tconn
4135 if (atomic_dec_and_test(&(tconn->kstc_refcount))) {
4137 spin_lock(&(tconn->kstc_lock));
4139 if ( ( tconn->kstc_type == kstt_child ||
4140 tconn->kstc_type == kstt_sender ) &&
4141 ( tconn->kstc_state == ksts_connected ) ) {
4143 spin_unlock(&(tconn->kstc_lock));
4145 ks_abort_tconn(tconn);
4149 if (cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY)) {
4150 cfs_enter_debugger();
4153 &(tconn->kstc_destroy),
4157 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY);
4160 spin_unlock(&(tconn->kstc_lock));
4167 * cleanup the tdi connection and free it
4170 * tconn: the tdi connection to be cleaned.
4181 ksock_tconn_t * tconn
4184 LASSERT(tconn->kstc_refcount.counter == 0);
4186 if (tconn->kstc_type == kstt_listener) {
4188 ks_reset_handlers(tconn);
4190 /* for listener, we just need to close the address object */
4192 tconn->kstc_addr.Handle,
4193 tconn->kstc_addr.FileObject
4196 tconn->kstc_state = ksts_inited;
4198 } else if (tconn->kstc_type == kstt_child) {
4200 /* for child tdi conections */
4202 /* disassociate the relation between it's connection object
4203 and the address object */
4205 if (tconn->kstc_state == ksts_associated) {
4206 KsDisassociateAddress(
4207 tconn->child.kstc_info.FileObject
4211 /* release the connection object */
4214 tconn->child.kstc_info.Handle,
4215 tconn->child.kstc_info.FileObject
4218 /* release it's refer of it's parent's address object */
4221 tconn->kstc_addr.FileObject
4224 spin_lock(&tconn->child.kstc_parent->kstc_lock);
4225 spin_lock(&tconn->kstc_lock);
4227 tconn->kstc_state = ksts_inited;
4229 /* remove it frome it's parent's queues */
4231 if (tconn->child.kstc_queued) {
4233 list_del(&(tconn->child.kstc_link));
4235 if (tconn->child.kstc_queueno) {
4237 LASSERT(tconn->child.kstc_parent->listener.kstc_accepted.num > 0);
4238 tconn->child.kstc_parent->listener.kstc_accepted.num -= 1;
4242 LASSERT(tconn->child.kstc_parent->listener.kstc_listening.num > 0);
4243 tconn->child.kstc_parent->listener.kstc_listening.num -= 1;
4246 tconn->child.kstc_queued = FALSE;
4249 spin_unlock(&tconn->kstc_lock);
4250 spin_unlock(&tconn->child.kstc_parent->kstc_lock);
4252 /* drop the reference of the parent tconn */
4253 ks_put_tconn(tconn->child.kstc_parent);
4255 } else if (tconn->kstc_type == kstt_sender) {
4257 ks_reset_handlers(tconn);
4259 /* release the connection object */
4262 tconn->sender.kstc_info.Handle,
4263 tconn->sender.kstc_info.FileObject
4266 /* release it's refer of it's parent's address object */
4268 tconn->kstc_addr.Handle,
4269 tconn->kstc_addr.FileObject
4272 tconn->kstc_state = ksts_inited;
4275 cfs_enter_debugger();
4278 /* free the tconn structure ... */
4280 ks_free_tconn(tconn);
4285 ksock_tconn_t * tconn,
4292 PKS_TSDUMGR KsTsduMgr;
4296 ks_get_tconn(tconn);
4297 spin_lock(&(tconn->kstc_lock));
4299 if ( tconn->kstc_type != kstt_sender &&
4300 tconn->kstc_type != kstt_child) {
4302 spin_unlock(&(tconn->kstc_lock));
4306 if (tconn->kstc_state != ksts_connected) {
4308 spin_unlock(&(tconn->kstc_lock));
4312 if (tconn->kstc_type == kstt_sender) {
4313 KsChain = &(tconn->sender.kstc_recv);
4315 LASSERT(tconn->kstc_type == kstt_child);
4316 KsChain = &(tconn->child.kstc_recv);
4320 KsTsduMgr = &(KsChain->Expedited);
4322 KsTsduMgr = &(KsChain->Normal);
4325 *size = KsTsduMgr->TotalBytes;
4326 spin_unlock(&(tconn->kstc_lock));
4330 ks_put_tconn(tconn);
4337 * Query the the options of the tcp stream connnection
4340 * tconn: the tdi connection
4342 * OptionValue: buffer to store the option value
4343 * Length: the length of the value, to be returned
4346 * int: ks return code
4354 ksock_tconn_t * tconn,
4360 NTSTATUS Status = STATUS_SUCCESS;
4362 IO_STATUS_BLOCK IoStatus;
4364 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfoEx;
4366 PFILE_OBJECT ConnectionObject;
4367 PDEVICE_OBJECT DeviceObject = NULL;
4370 PIO_STACK_LOCATION IrpSp = NULL;
4374 /* make sure the tdi connection is connected ? */
4376 ks_get_tconn(tconn);
4378 if (tconn->kstc_state != ksts_connected) {
4379 Status = STATUS_INVALID_PARAMETER;
4383 LASSERT(tconn->kstc_type == kstt_sender ||
4384 tconn->kstc_type == kstt_child);
4386 if (tconn->kstc_type == kstt_sender) {
4387 ConnectionObject = tconn->sender.kstc_info.FileObject;
4389 ConnectionObject = tconn->child.kstc_info.FileObject;
4392 QueryInfoEx.ID.toi_id = ID;
4393 QueryInfoEx.ID.toi_type = INFO_TYPE_CONNECTION;
4394 QueryInfoEx.ID.toi_class = INFO_CLASS_PROTOCOL;
4395 QueryInfoEx.ID.toi_entity.tei_entity = CO_TL_ENTITY;
4396 QueryInfoEx.ID.toi_entity.tei_instance = 0;
4398 RtlZeroMemory(&(QueryInfoEx.Context), CONTEXT_SIZE);
4400 KeInitializeEvent(&Event, NotificationEvent, FALSE);
4401 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4403 Irp = IoBuildDeviceIoControlRequest(
4404 IOCTL_TCP_QUERY_INFORMATION_EX,
4407 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
4416 Status = STATUS_INSUFFICIENT_RESOURCES;
4420 IrpSp = IoGetNextIrpStackLocation(Irp);
4422 if (IrpSp == NULL) {
4426 Status = STATUS_INSUFFICIENT_RESOURCES;
4430 IrpSp->FileObject = ConnectionObject;
4431 IrpSp->DeviceObject = DeviceObject;
4433 Status = IoCallDriver(DeviceObject, Irp);
4435 if (Status == STATUS_PENDING) {
4437 KeWaitForSingleObject(
4445 Status = IoStatus.Status;
4449 if (NT_SUCCESS(Status)) {
4450 *Length = IoStatus.Information;
4452 cfs_enter_debugger();
4453 memset(OptionValue, 0, *Length);
4454 Status = STATUS_SUCCESS;
4459 ks_put_tconn(tconn);
4461 return cfs_error_code(Status);
4466 * Set the the options for the tcp stream connnection
4469 * tconn: the tdi connection
4471 * OptionValue: buffer containing the new option value
4472 * Length: the length of the value
4475 * int: ks return code
4483 ksock_tconn_t * tconn,
4489 NTSTATUS Status = STATUS_SUCCESS;
4491 IO_STATUS_BLOCK IoStatus;
4493 ULONG SetInfoExLength;
4494 PTCP_REQUEST_SET_INFORMATION_EX SetInfoEx = NULL;
4496 PFILE_OBJECT ConnectionObject;
4497 PDEVICE_OBJECT DeviceObject = NULL;
4500 PIO_STACK_LOCATION IrpSp = NULL;
4504 /* make sure the tdi connection is connected ? */
4506 ks_get_tconn(tconn);
4508 if (tconn->kstc_state != ksts_connected) {
4509 Status = STATUS_INVALID_PARAMETER;
4513 LASSERT(tconn->kstc_type == kstt_sender ||
4514 tconn->kstc_type == kstt_child);
4516 if (tconn->kstc_type == kstt_sender) {
4517 ConnectionObject = tconn->sender.kstc_info.FileObject;
4519 ConnectionObject = tconn->child.kstc_info.FileObject;
4522 SetInfoExLength = sizeof(TCP_REQUEST_SET_INFORMATION_EX) - 1 + Length + sizeof(KEVENT);
4524 SetInfoEx = ExAllocatePoolWithTag(
4530 if (SetInfoEx == NULL) {
4531 Status = STATUS_INSUFFICIENT_RESOURCES;
4535 SetInfoEx->ID.toi_id = ID;
4537 SetInfoEx->ID.toi_type = INFO_TYPE_CONNECTION;
4538 SetInfoEx->ID.toi_class = INFO_CLASS_PROTOCOL;
4539 SetInfoEx->ID.toi_entity.tei_entity = CO_TL_ENTITY;
4540 SetInfoEx->ID.toi_entity.tei_instance = TL_INSTANCE;
4542 SetInfoEx->BufferSize = Length;
4543 RtlCopyMemory(&(SetInfoEx->Buffer[0]), OptionValue, Length);
4545 Event = (PKEVENT)(&(SetInfoEx->Buffer[Length]));
4546 KeInitializeEvent(Event, NotificationEvent, FALSE);
4548 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4550 Irp = IoBuildDeviceIoControlRequest(
4551 IOCTL_TCP_SET_INFORMATION_EX,
4563 Status = STATUS_INSUFFICIENT_RESOURCES;
4567 IrpSp = IoGetNextIrpStackLocation(Irp);
4569 if (IrpSp == NULL) {
4572 Status = STATUS_INSUFFICIENT_RESOURCES;
4576 IrpSp->FileObject = ConnectionObject;
4577 IrpSp->DeviceObject = DeviceObject;
4579 Status = IoCallDriver(DeviceObject, Irp);
4581 if (Status == STATUS_PENDING) {
4583 KeWaitForSingleObject(
4591 Status = IoStatus.Status;
4597 ExFreePool(SetInfoEx);
4600 if (!NT_SUCCESS(Status)) {
4601 printk("ks_set_tcp_option: error setup tcp option: ID (%d), Status = %xh\n",
4603 Status = STATUS_SUCCESS;
4606 ks_put_tconn(tconn);
4608 return cfs_error_code(Status);
4613 * bind the tdi connection object with an address
4616 * tconn: tconn to be bound
4617 * parent: the parent tconn object
4618 * ipaddr: the ip address
4619 * port: the port number
4622 * int: 0 for success or ks error codes.
4630 ksock_tconn_t * tconn,
4631 ksock_tconn_t * parent,
4639 ksock_tdi_addr_t taddr;
4641 memset(&taddr, 0, sizeof(ksock_tdi_addr_t));
4643 if (tconn->kstc_state != ksts_inited) {
4645 status = STATUS_INVALID_PARAMETER;
4646 rc = cfs_error_code(status);
4650 } else if (tconn->kstc_type == kstt_child) {
4652 if (NULL == parent) {
4653 status = STATUS_INVALID_PARAMETER;
4654 rc = cfs_error_code(status);
4659 /* refer it's parent's address object */
4661 taddr = parent->kstc_addr;
4662 ObReferenceObject(taddr.FileObject);
4664 ks_get_tconn(parent);
4668 PTRANSPORT_ADDRESS TdiAddress = &(taddr.Tdi);
4671 /* intialize the tdi address*/
4673 TdiAddress->TAAddressCount = 1;
4674 TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
4675 TdiAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
4677 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
4678 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
4680 memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
4683 /* open the transport address object */
4685 AddrLen = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) +
4686 TDI_ADDRESS_LENGTH_IP;
4688 status = KsOpenAddress(
4696 if (!NT_SUCCESS(status)) {
4698 KsPrint((0, "ks_bind_tconn: failed to open ip addr object (%x:%d), status = %xh\n",
4699 addr, port, status ));
4700 rc = cfs_error_code(status);
4705 if (tconn->kstc_type == kstt_child) {
4706 tconn->child.kstc_parent = parent;
4709 tconn->kstc_state = ksts_bind;
4710 tconn->kstc_addr = taddr;
4719 * build tcp/streaming connection to remote peer
4722 * tconn: tconn to be connected to the peer
4723 * addr: the peer's ip address
4724 * port: the peer's port number
4727 * int: 0 for success or ks error codes.
4735 ksock_tconn_t * tconn,
4741 NTSTATUS status = STATUS_SUCCESS;
4744 PFILE_OBJECT ConnectionObject = NULL;
4745 PDEVICE_OBJECT DeviceObject = NULL;
4747 PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
4752 LASSERT(tconn->kstc_type == kstt_sender);
4753 LASSERT(tconn->kstc_state == ksts_bind);
4755 ks_get_tconn(tconn);
4758 /* set the event callbacks */
4759 rc = ks_set_handlers(tconn);
4762 cfs_enter_debugger();
4767 /* create the connection file handle / object */
4768 status = KsOpenConnection(
4770 (CONNECTION_CONTEXT)tconn,
4771 &(tconn->sender.kstc_info.Handle),
4772 &(tconn->sender.kstc_info.FileObject)
4775 if (!NT_SUCCESS(status)) {
4776 rc = cfs_error_code(status);
4777 cfs_enter_debugger();
4781 /* associdate the the connection with the adress object of the tconn */
4783 status = KsAssociateAddress(
4784 tconn->kstc_addr.Handle,
4785 tconn->sender.kstc_info.FileObject
4788 if (!NT_SUCCESS(status)) {
4789 rc = cfs_error_code(status);
4790 cfs_enter_debugger();
4794 tconn->kstc_state = ksts_associated;
4796 /* Allocating Connection Info Together with the Address */
4797 AddrLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
4798 + TDI_ADDRESS_LENGTH_IP;
4800 ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
4801 NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + AddrLength, 'iCsK');
4803 if (NULL == ConnectionInfo) {
4805 status = STATUS_INSUFFICIENT_RESOURCES;
4806 rc = cfs_error_code(status);
4807 cfs_enter_debugger();
4811 /* Initializing ConnectionInfo ... */
4813 PTRANSPORT_ADDRESS TdiAddress;
4815 /* ConnectionInfo settings */
4817 ConnectionInfo->UserDataLength = 0;
4818 ConnectionInfo->UserData = NULL;
4819 ConnectionInfo->OptionsLength = 0;
4820 ConnectionInfo->Options = NULL;
4821 ConnectionInfo->RemoteAddressLength = AddrLength;
4822 ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
4825 /* intialize the tdi address*/
4827 TdiAddress = ConnectionInfo->RemoteAddress;
4829 TdiAddress->TAAddressCount = 1;
4830 TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
4831 TdiAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
4833 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
4834 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
4836 memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
4839 /* Now prepare to connect the remote peer ... */
4841 ConnectionObject = tconn->sender.kstc_info.FileObject;
4842 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4844 /* allocate a new Irp */
4846 Irp = KsBuildTdiIrp(DeviceObject);
4850 status = STATUS_INSUFFICIENT_RESOURCES;
4851 rc = cfs_error_code(status);
4852 cfs_enter_debugger();
4870 /* sumbit the Irp to the underlying transport driver */
4871 status = KsSubmitTdiIrp(
4878 spin_lock(&(tconn->kstc_lock));
4880 if (NT_SUCCESS(status)) {
4882 /* Connected! the conneciton is built successfully. */
4884 tconn->kstc_state = ksts_connected;
4886 tconn->sender.kstc_info.ConnectionInfo = ConnectionInfo;
4887 tconn->sender.kstc_info.Remote = ConnectionInfo->RemoteAddress;
4889 spin_unlock(&(tconn->kstc_lock));
4893 /* Not connected! Abort it ... */
4896 cfs_enter_debugger();
4900 rc = cfs_error_code(status);
4902 tconn->kstc_state = ksts_associated;
4903 spin_unlock(&(tconn->kstc_lock));
4905 /* disassocidate the connection and the address object,
4906 after cleanup, it's safe to set the state to abort ... */
4908 if ( NT_SUCCESS(KsDisassociateAddress(
4909 tconn->sender.kstc_info.FileObject))) {
4910 tconn->kstc_state = ksts_aborted;
4913 /* reset the event callbacks */
4914 rc = ks_reset_handlers(tconn);
4921 if (NT_SUCCESS(status)) {
4923 ks_query_local_ipaddr(tconn);
4927 if (ConnectionInfo) {
4928 ExFreePool(ConnectionInfo);
4935 ks_put_tconn(tconn);
4942 * ks_disconnect_tconn
4943 * disconnect the tconn from a connection
4946 * tconn: the tdi connecton object connected already
4947 * flags: flags & options for disconnecting
4950 * int: ks error code
4957 ks_disconnect_tconn(
4958 ksock_tconn_t * tconn,
4962 NTSTATUS status = STATUS_SUCCESS;
4964 ksock_tconn_info_t * info;
4966 PFILE_OBJECT ConnectionObject;
4967 PDEVICE_OBJECT DeviceObject = NULL;
4973 ks_get_tconn(tconn);
4975 /* make sure tt's connected already and it
4976 must be a sender or a child ... */
4978 LASSERT(tconn->kstc_state == ksts_connected);
4979 LASSERT( tconn->kstc_type == kstt_sender ||
4980 tconn->kstc_type == kstt_child);
4982 /* reset all the event handlers to NULL */
4984 if (tconn->kstc_type != kstt_child) {
4985 ks_reset_handlers (tconn);
4988 /* Disconnecting to the remote peer ... */
4990 if (tconn->kstc_type == kstt_sender) {
4991 info = &(tconn->sender.kstc_info);
4993 info = &(tconn->child.kstc_info);
4996 ConnectionObject = info->FileObject;
4997 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4999 /* allocate an Irp and setup it */
5001 Irp = KsBuildTdiIrp(DeviceObject);
5005 status = STATUS_INSUFFICIENT_RESOURCES;
5006 cfs_enter_debugger();
5012 SynchronizationEvent,
5020 KsDisconectCompletionRoutine,
5028 /* issue the Irp to the underlying transport
5029 driver to disconnect the connection */
5031 status = IoCallDriver(DeviceObject, Irp);
5033 if (STATUS_PENDING == status) {
5035 status = KeWaitForSingleObject(
5043 status = Irp->IoStatus.Status;
5046 KsPrint((2, "KsDisconnect: Disconnection is done with Status = %xh (%s) ...\n",
5047 status, KsNtStatusToString(status)));
5051 if (info->ConnectionInfo) {
5053 /* disassociate the association between connection/address objects */
5055 status = KsDisassociateAddress(ConnectionObject);
5057 if (!NT_SUCCESS(status)) {
5058 cfs_enter_debugger();
5061 spin_lock(&(tconn->kstc_lock));
5063 /* cleanup the tsdumgr Lists */
5064 KsCleanupTsdu (tconn);
5066 /* set the state of the tconn */
5067 if (NT_SUCCESS(status)) {
5068 tconn->kstc_state = ksts_disconnected;
5070 tconn->kstc_state = ksts_associated;
5073 /* free the connection info to system pool*/
5074 ExFreePool(info->ConnectionInfo);
5075 info->ConnectionInfo = NULL;
5076 info->Remote = NULL;
5078 spin_unlock(&(tconn->kstc_lock));
5081 status = STATUS_SUCCESS;
5085 ks_put_tconn(tconn);
5087 return cfs_error_code(status);
5093 * The connection is broken un-expectedly. We need do
5097 * tconn: the tdi connection
5108 ksock_tconn_t * tconn
5111 PKS_DISCONNECT_WORKITEM WorkItem = NULL;
5113 WorkItem = &(tconn->kstc_disconnect);
5115 ks_get_tconn(tconn);
5116 spin_lock(&(tconn->kstc_lock));
5118 if (tconn->kstc_state != ksts_connected) {
5119 ks_put_tconn(tconn);
5122 if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
5124 WorkItem->Flags = TDI_DISCONNECT_ABORT;
5125 WorkItem->tconn = tconn;
5127 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
5130 &(WorkItem->WorkItem),
5136 spin_unlock(&(tconn->kstc_lock));
5141 * ks_query_local_ipaddr
5142 * query the local connection ip address
5145 * tconn: the tconn which is connected
5148 * int: ks error code
5155 ks_query_local_ipaddr(
5156 ksock_tconn_t * tconn
5159 PFILE_OBJECT FileObject = NULL;
5162 PTRANSPORT_ADDRESS TdiAddress;
5163 ULONG AddressLength;
5165 if (tconn->kstc_type == kstt_sender) {
5166 FileObject = tconn->sender.kstc_info.FileObject;
5167 } else if (tconn->kstc_type == kstt_child) {
5168 FileObject = tconn->child.kstc_info.FileObject;
5170 status = STATUS_INVALID_PARAMETER;
5174 TdiAddress = &(tconn->kstc_addr.Tdi);
5175 AddressLength = MAX_ADDRESS_LENGTH;
5177 status = KsQueryIpAddress(FileObject, TdiAddress, &AddressLength);
5179 if (NT_SUCCESS(status)) {
5181 KsPrint((0, "ks_query_local_ipaddr: Local ip address = %xh port = %xh\n",
5182 ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->in_addr,
5183 ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->sin_port ));
5185 KsPrint((0, "KsQueryonnectionIpAddress: Failed to query the connection local ip address.\n"));
5190 return cfs_error_code(status);
5195 * send MDL chain to the peer for a stream connection
5198 * tconn: tdi connection object
5199 * tx: the transmit context
5200 * mdl: the mdl chain containing the data
5201 * len: length of the data
5202 * flags: flags of the transmission
5213 ksock_tconn_t * tconn,
5224 ksock_tdi_tx_t * context;
5227 PKS_TSDUMGR KsTsduMgr;
5229 PKS_TSDU_BUF KsTsduBuf;
5230 PKS_TSDU_DAT KsTsduDat;
5232 BOOLEAN bNewTsdu = FALSE; /* newly allocated */
5233 BOOLEAN bNewBuff = FALSE; /* newly allocated */
5235 BOOLEAN bBuffed; /* bufferred sending */
5237 PUCHAR Buffer = NULL;
5238 ksock_mdl_t * NewMdl = NULL;
5241 PFILE_OBJECT ConnObject;
5242 PDEVICE_OBJECT DeviceObject;
5244 BOOLEAN bIsNonBlock;
5246 ks_get_tconn(tconn);
5248 tflags = ks_tdi_send_flags(flags);
5249 bIsNonBlock = cfs_is_flag_set(flags, MSG_DONTWAIT);
5251 spin_lock(&tconn->kstc_lock);
5253 LASSERT( tconn->kstc_type == kstt_sender ||
5254 tconn->kstc_type == kstt_child );
5256 if (tconn->kstc_state != ksts_connected) {
5257 spin_unlock(&tconn->kstc_lock);
5258 ks_put_tconn(tconn);
5262 /* get the latest Tsdu buffer form TsduMgr list.
5263 just set NULL if the list is empty. */
5265 if (tconn->kstc_type == kstt_sender) {
5266 KsChain = &(tconn->sender.kstc_send);
5268 LASSERT(tconn->kstc_type == kstt_child);
5269 KsChain = &(tconn->child.kstc_send);
5272 if (cfs_is_flag_set(tflags, TDI_SEND_EXPEDITED)) {
5273 KsTsduMgr = &(KsChain->Expedited);
5275 KsTsduMgr = &(KsChain->Normal);
5278 if (KsTsduMgr->TotalBytes + len <= tconn->kstc_snd_wnd) {
5284 /* do the preparation work for bufferred sending */
5288 /* if the data is even larger than the biggest Tsdu, we have
5289 to allocate new buffer and use TSDU_TYOE_BUF to store it */
5291 if ( KS_TSDU_STRU_SIZE((ULONG)len) > ks_data.ksnd_tsdu_size
5292 - KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
5296 if (list_empty(&(KsTsduMgr->TsduList))) {
5298 LASSERT(KsTsduMgr->NumOfTsdu == 0);
5303 LASSERT(KsTsduMgr->NumOfTsdu > 0);
5304 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
5305 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
5308 /* check whether KsTsdu free space is enough, or we need alloc new Tsdu */
5310 if (sizeof(KS_TSDU_BUF) + KsTsdu->LastOffset > KsTsdu->TotalLength) {
5314 if ( KS_TSDU_STRU_SIZE((ULONG)len) >
5315 KsTsdu->TotalLength - KsTsdu->LastOffset ) {
5321 /* if there's no Tsdu or the free size is not enough for the
5322 KS_TSDU_BUF or KS_TSDU_DAT. We need re-allocate a new Tsdu. */
5324 if (NULL == KsTsdu) {
5326 KsTsdu = KsAllocateKsTsdu();
5328 if (NULL == KsTsdu) {
5336 /* process the case that a new buffer is to be allocated from system memory */
5339 /* now allocating internal buffer to contain the payload */
5340 Buffer = ExAllocatePool(NonPagedPool, len);
5342 if (NULL == Buffer) {
5352 /* queue a new KS_TSDU_BUF to the Tsdu buffer */
5353 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
5355 KsTsduBuf->TsduFlags = 0;
5356 KsTsduBuf->DataLength = (ULONG)len;
5357 KsTsduBuf->StartOffset = 0;
5358 KsTsduBuf->UserBuffer = Buffer;
5360 /* queue a new KS_TSDU_BUF to the Tsdu buffer */
5361 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
5363 KsTsduDat->TsduFlags = 0;
5364 KsTsduDat->DataLength = (ULONG)len;
5365 KsTsduDat->StartOffset = 0;
5366 KsTsduDat->TotalLength = KS_TSDU_STRU_SIZE((ULONG)len);
5368 Buffer = &KsTsduDat->Data[0];
5371 /* now locking the Buffer and copy user payload into the buffer */
5372 ASSERT(Buffer != NULL);
5374 rc = ks_lock_buffer(Buffer, FALSE, len, IoReadAccess, &NewMdl);
5376 printk("ks_send_mdl: bufferred: error allocating mdl.\n");
5379 ULONG BytesCopied = 0;
5380 TdiCopyMdlToBuffer(mdl, 0, Buffer, 0, (ULONG)len, &BytesCopied);
5381 if (BytesCopied != (ULONG) len) {
5386 /* Do the finializing job if we succeed to to lock the buffer and move
5387 user data. Or we need do cleaning up ... */
5391 KsTsduBuf->TsduType = TSDU_TYPE_BUF;
5392 KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
5395 KsTsduDat->TsduType = TSDU_TYPE_DAT;
5396 KsTsdu->LastOffset += KsTsduDat->TotalLength;
5399 /* attach it to the TsduMgr list if the Tsdu is newly created. */
5402 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
5403 KsTsduMgr->NumOfTsdu++;
5409 ks_release_mdl(NewMdl, FALSE);
5421 /* update the TotalBytes being in sending */
5422 KsTsduMgr->TotalBytes += (ULONG)len;
5424 spin_unlock(&tconn->kstc_lock);
5426 /* cleanup the Tsdu if not successful */
5427 if (!bBuffed && bNewTsdu) {
5428 KsPutKsTsdu(KsTsdu);
5433 /* we need allocate the ksock_tx_t structure from memory pool. */
5435 context = cfs_alloc(sizeof(ksock_tdi_tx_t) + sizeof(KEVENT),0);
5437 /* release the chained mdl */
5438 ks_release_mdl(mdl, FALSE);
5440 Status = STATUS_INSUFFICIENT_RESOURCES;
5444 /* intialize the TcpContext */
5446 memset(context,0, sizeof(ksock_tdi_tx_t) + sizeof(KEVENT));
5448 context->tconn = tconn;
5449 context->Event = (PKEVENT) ((PUCHAR)context + sizeof(ksock_tdi_tx_t));
5451 KeInitializeEvent(context->Event, SynchronizationEvent, FALSE);
5455 /* for bufferred transmission, we need set
5456 the internal completion routine. */
5458 context->CompletionRoutine = KsTcpSendCompletionRoutine;
5459 context->KsTsduMgr = KsTsduMgr;
5460 context->CompletionContext = KsTsdu;
5461 context->CompletionContext2 = (bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat);
5462 context->bCounted = FALSE;
5464 } else if (bIsNonBlock) {
5466 /* for non-blocking transmission, we need set
5467 the internal completion routine too. */
5469 context->CompletionRoutine = KsTcpSendCompletionRoutine;
5470 context->CompletionContext = tx;
5471 context->KsTsduMgr = KsTsduMgr;
5472 context->bCounted = TRUE;
5473 context->ReferCount = 2;
5476 if (tconn->kstc_type == kstt_sender) {
5477 ConnObject = tconn->sender.kstc_info.FileObject;
5479 LASSERT(tconn->kstc_type == kstt_child);
5480 ConnObject = tconn->child.kstc_info.FileObject;
5483 DeviceObject = IoGetRelatedDeviceObject(ConnObject);
5485 Irp = KsBuildTdiIrp(DeviceObject);
5489 /* release the chained mdl */
5490 ks_release_mdl(mdl, FALSE);
5492 Status = STATUS_INSUFFICIENT_RESOURCES;
5496 length = KsQueryMdlsSize(mdl);
5498 LASSERT((ULONG)len <= length);
5500 ks_get_tconn(tconn);
5506 KsTcpCompletionRoutine,
5508 (bBuffed ? NewMdl : mdl),
5509 (bBuffed ? (tflags | TDI_SEND_NON_BLOCKING) : tflags),
5513 Status = IoCallDriver(DeviceObject, Irp);
5516 ks_release_mdl(mdl, FALSE);
5520 if (!NT_SUCCESS(Status)) {
5521 cfs_enter_debugger();
5522 rc = cfs_error_code(Status);
5527 Status = STATUS_SUCCESS;
5532 if (InterlockedDecrement(&context->ReferCount) == 0) {
5533 Status = Irp->IoStatus.Status;
5535 Status = STATUS_PENDING;
5539 if (STATUS_PENDING == Status) {
5540 Status = KeWaitForSingleObject(
5548 if (NT_SUCCESS(Status)) {
5549 Status = Irp->IoStatus.Status;
5554 if (Status == STATUS_SUCCESS) {
5555 rc = (int)(Irp->IoStatus.Information);
5557 spin_lock(&tconn->kstc_lock);
5558 KsTsduMgr->TotalBytes -= rc;
5559 spin_unlock(&tconn->kstc_lock);
5562 rc = cfs_error_code(Status);
5571 ks_release_mdl(NewMdl, FALSE);
5576 if (!NT_SUCCESS(Status)) {
5584 if (Status != STATUS_PENDING) {
5588 /* Freeing the Irp ... */
5596 if (!NT_SUCCESS(Status)) {
5598 spin_lock(&tconn->kstc_lock);
5600 KsTsduMgr->TotalBytes -= (ULONG)len;
5604 /* attach it to the TsduMgr list if the Tsdu is newly created. */
5607 list_del(&(KsTsdu->Link));
5608 KsTsduMgr->NumOfTsdu--;
5610 KsPutKsTsdu(KsTsdu);
5613 if ( (ulong_ptr)KsTsduBuf + sizeof(KS_TSDU_BUF) ==
5614 (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
5615 KsTsdu->LastOffset -= sizeof(KS_TSDU_BUF);
5616 KsTsduBuf->TsduType = 0;
5618 cfs_enter_debugger();
5619 KsTsduBuf->StartOffset = KsTsduBuf->DataLength;
5622 if ( (ulong_ptr)KsTsduDat + KsTsduDat->TotalLength ==
5623 (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
5624 KsTsdu->LastOffset -= KsTsduDat->TotalLength;
5625 KsTsduDat->TsduType = 0;
5627 cfs_enter_debugger();
5628 KsTsduDat->StartOffset = KsTsduDat->DataLength;
5634 spin_unlock(&tconn->kstc_lock);
5637 /* free the context if is not used at all */
5642 ks_put_tconn(tconn);
5649 * Receive data from the peer for a stream connection
5652 * tconn: tdi connection object
5653 * mdl: the mdl chain to contain the incoming data
5654 * len: length of the data
5655 * flags: flags of the receiving
5666 ksock_tconn_t * tconn,
5672 NTSTATUS Status = STATUS_SUCCESS;
5675 BOOLEAN bIsNonBlock;
5676 BOOLEAN bIsExpedited;
5679 PKS_TSDUMGR KsTsduMgr;
5681 PKS_TSDU_DAT KsTsduDat;
5682 PKS_TSDU_BUF KsTsduBuf;
5683 PKS_TSDU_MDL KsTsduMdl;
5687 ULONG BytesRecved = 0;
5690 bIsNonBlock = cfs_is_flag_set(flags, MSG_DONTWAIT);
5691 bIsExpedited = cfs_is_flag_set(flags, MSG_OOB);
5693 ks_get_tconn(tconn);
5699 spin_lock(&(tconn->kstc_lock));
5701 if ( tconn->kstc_type != kstt_sender &&
5702 tconn->kstc_type != kstt_child) {
5705 spin_unlock(&(tconn->kstc_lock));
5710 if (tconn->kstc_state != ksts_connected) {
5713 spin_unlock(&(tconn->kstc_lock));
5718 if (tconn->kstc_type == kstt_sender) {
5719 KsChain = &(tconn->sender.kstc_recv);
5721 LASSERT(tconn->kstc_type == kstt_child);
5722 KsChain = &(tconn->child.kstc_recv);
5726 KsTsduMgr = &(KsChain->Expedited);
5728 KsTsduMgr = &(KsChain->Normal);
5733 if (list_empty(&(KsTsduMgr->TsduList))) {
5736 // It's a notification event. We need reset it to
5737 // un-signaled state in case there no any tsdus.
5740 KeResetEvent(&(KsTsduMgr->Event));
5744 KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
5745 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
5747 /* remove the KsTsdu from TsduMgr list to release the lock */
5748 list_del(&(KsTsdu->Link));
5749 KsTsduMgr->NumOfTsdu--;
5751 spin_unlock(&(tconn->kstc_lock));
5753 while ((ULONG)size > BytesRecved) {
5755 ULONG BytesCopied = 0;
5756 ULONG BytesToCopy = 0;
5757 ULONG StartOffset = 0;
5759 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5760 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5761 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5763 if ( TSDU_TYPE_DAT == KsTsduDat->TsduType ||
5764 TSDU_TYPE_BUF == KsTsduBuf->TsduType ) {
5768 // Data Tsdu Unit ...
5771 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
5773 if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
5774 /* data is not ready yet*/
5775 KeResetEvent(&(KsTsduMgr->Event));
5776 printk("ks_recv_mdl: KsTsduDat (%xh) is not ready yet !!!!!!!\n", KsTsduDat);
5780 Buffer = &KsTsduDat->Data[0];
5781 StartOffset = KsTsduDat->StartOffset;
5782 if (KsTsduDat->DataLength - KsTsduDat->StartOffset > size - BytesRecved) {
5783 /* Recvmsg requst could be statisfied ... */
5784 BytesToCopy = size - BytesRecved;
5786 BytesToCopy = KsTsduDat->DataLength - KsTsduDat->StartOffset;
5791 if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
5792 /* data is not ready yet*/
5793 KeResetEvent(&(KsTsduMgr->Event));
5794 DbgPrint("ks_recv_mdl: KsTsduBuf (%xh) is not ready yet !!!!!!!\n", KsTsduBuf);
5798 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
5799 Buffer = KsTsduBuf->UserBuffer;
5800 StartOffset = KsTsduBuf->StartOffset;
5802 if (KsTsduBuf->DataLength - KsTsduBuf->StartOffset > size - BytesRecved) {
5803 /* Recvmsg requst could be statisfied ... */
5804 BytesToCopy = size - BytesRecved;
5806 BytesToCopy = KsTsduBuf->DataLength - KsTsduBuf->StartOffset;
5810 if (BytesToCopy > 0) {
5811 Status = TdiCopyBufferToMdl(
5820 if (NT_SUCCESS(Status)) {
5822 if (BytesToCopy != BytesCopied) {
5823 cfs_enter_debugger();
5826 BytesRecved += BytesCopied;
5827 RecvedOnce += BytesCopied;
5831 cfs_enter_debugger();
5833 if (STATUS_BUFFER_OVERFLOW == Status) {
5838 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
5840 KsTsduDat->StartOffset += BytesCopied;
5842 if (KsTsduDat->StartOffset == KsTsduDat->DataLength) {
5843 KsTsdu->StartOffset += KsTsduDat->TotalLength;
5848 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
5849 KsTsduBuf->StartOffset += BytesCopied;
5850 if (KsTsduBuf->StartOffset == KsTsduBuf->DataLength) {
5851 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
5852 /* now we need release the buf to system pool */
5853 ExFreePool(KsTsduBuf->UserBuffer);
5857 } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
5860 // MDL Tsdu Unit ...
5863 if (KsTsduMdl->DataLength > size - BytesRecved) {
5865 /* Recvmsg requst could be statisfied ... */
5867 BytesToCopy = size - BytesRecved;
5871 BytesToCopy = KsTsduMdl->DataLength;
5874 Status = KsCopyMdlChainToMdlChain(
5876 KsTsduMdl->StartOffset,
5883 if (NT_SUCCESS(Status)) {
5885 if (BytesToCopy != BytesCopied) {
5886 cfs_enter_debugger();
5889 KsTsduMdl->StartOffset += BytesCopied;
5890 KsTsduMdl->DataLength -= BytesCopied;
5892 BytesRecved += BytesCopied;
5893 RecvedOnce += BytesCopied;
5895 cfs_enter_debugger();
5898 if (0 == KsTsduMdl->DataLength) {
5901 // Call TdiReturnChainedReceives to release the Tsdu memory
5904 TdiReturnChainedReceives(
5905 &(KsTsduMdl->Descriptor),
5908 KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
5912 printk("ks_recv_mdl: unknown tsdu slot: slot = %x type = %x Start= %x\n",
5913 KsTsduDat, KsTsduDat->TsduType, KsTsduDat->StartOffset, KsTsduDat->DataLength);
5914 printk(" Tsdu = %x Magic=%x: Start = %x Last = %x Length = %x",
5915 KsTsdu, KsTsdu->Magic, KsTsdu->StartOffset, KsTsdu->LastOffset, KsTsdu->TotalLength);
5916 cfs_enter_debugger();
5919 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
5922 // KsTsdu is empty now, we need free it ...
5925 KsPutKsTsdu(KsTsdu);
5932 spin_lock(&(tconn->kstc_lock));
5934 /* we need attach the KsTsdu to the list header */
5936 KsTsduMgr->NumOfTsdu++;
5937 list_add(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
5938 } else if ((ULONG)size > BytesRecved) {
5943 if (KsTsduMgr->TotalBytes < RecvedOnce) {
5944 cfs_enter_debugger();
5945 KsTsduMgr->TotalBytes = 0;
5947 KsTsduMgr->TotalBytes -= RecvedOnce;
5950 spin_unlock(&(tconn->kstc_lock));
5952 if (NT_SUCCESS(Status)) {
5954 if ((BytesRecved < (ulong_ptr)size) && (!bIsNonBlock)) {
5956 KeWaitForSingleObject(
5957 &(KsTsduMgr->Event),
5967 if (bIsNonBlock && (BytesRecved == 0)) {
5976 ks_put_tconn(tconn);
5979 KsPrint((1, "ks_recv_mdl: recvieving %d bytes ...\n", rc));
5981 KsPrint((0, "ks_recv_mdl: recvieving error code = %d Stauts = %xh ...\n", rc, Status));
5984 /* release the chained mdl */
5985 ks_release_mdl(mdl, FALSE);
5993 * initialize the global data in ksockal_data
5999 * int: ks error code
6010 /* initialize tconn related globals */
6011 RtlZeroMemory(&ks_data, sizeof(ks_data_t));
6013 spin_lock_init(&ks_data.ksnd_tconn_lock);
6014 CFS_INIT_LIST_HEAD(&ks_data.ksnd_tconns);
6015 cfs_init_event(&ks_data.ksnd_tconn_exit, TRUE, FALSE);
6017 ks_data.ksnd_tconn_slab = cfs_mem_cache_create(
6018 "tcon", sizeof(ksock_tconn_t) , 0, 0);
6020 if (!ks_data.ksnd_tconn_slab) {
6025 /* initialize tsdu related globals */
6027 spin_lock_init(&ks_data.ksnd_tsdu_lock);
6028 CFS_INIT_LIST_HEAD(&ks_data.ksnd_freetsdus);
6029 ks_data.ksnd_tsdu_size = TDINAL_TSDU_DEFAULT_SIZE; /* 64k */
6030 ks_data.ksnd_tsdu_slab = cfs_mem_cache_create(
6031 "tsdu", ks_data.ksnd_tsdu_size, 0, 0);
6033 if (!ks_data.ksnd_tsdu_slab) {
6035 cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
6036 ks_data.ksnd_tconn_slab = NULL;
6040 /* initialize daemon related globals */
6042 spin_lock_init(&ks_data.ksnd_daemon_lock);
6043 CFS_INIT_LIST_HEAD(&ks_data.ksnd_daemons);
6044 cfs_init_event(&ks_data.ksnd_daemon_exit, TRUE, FALSE);
6046 KsRegisterPnpHandlers();
6056 * finalize the global data in ksockal_data
6062 * int: ks error code
6071 PKS_TSDU KsTsdu = NULL;
6072 struct list_head * list = NULL;
6074 /* clean up the pnp handler and address slots */
6075 KsDeregisterPnpHandlers();
6077 /* we need wait until all the tconn are freed */
6078 spin_lock(&(ks_data.ksnd_tconn_lock));
6080 if (list_empty(&(ks_data.ksnd_tconns))) {
6081 cfs_wake_event(&ks_data.ksnd_tconn_exit);
6083 spin_unlock(&(ks_data.ksnd_tconn_lock));
6085 /* now wait on the tconn exit event */
6086 cfs_wait_event(&ks_data.ksnd_tconn_exit, 0);
6088 /* it's safe to delete the tconn slab ... */
6089 cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
6090 ks_data.ksnd_tconn_slab = NULL;
6092 /* clean up all the tsud buffers in the free list */
6093 spin_lock(&(ks_data.ksnd_tsdu_lock));
6094 list_for_each (list, &ks_data.ksnd_freetsdus) {
6095 KsTsdu = list_entry (list, KS_TSDU, Link);
6098 ks_data.ksnd_tsdu_slab,
6101 spin_unlock(&(ks_data.ksnd_tsdu_lock));
6103 /* it's safe to delete the tsdu slab ... */
6104 cfs_mem_cache_destroy(ks_data.ksnd_tsdu_slab);
6105 ks_data.ksnd_tsdu_slab = NULL;
6107 /* good! it's smooth to do the cleaning up...*/
6111 * ks_create_child_tconn
6112 * Create the backlog child connection for a listener
6115 * parent: the listener daemon connection
6118 * the child connection or NULL in failure
6125 ks_create_child_tconn(
6126 ksock_tconn_t * parent
6130 ksock_tconn_t * backlog;
6132 /* allocate the tdi connecton object */
6133 backlog = ks_create_tconn();
6139 /* initialize the tconn as a child */
6140 ks_init_child(backlog);
6144 if (ks_bind_tconn(backlog, parent, 0, 0) < 0) {
6145 ks_free_tconn(backlog);
6150 /* open the connection object */
6151 status = KsOpenConnection(
6152 &(backlog->kstc_dev),
6154 &(backlog->child.kstc_info.Handle),
6155 &(backlog->child.kstc_info.FileObject)
6158 if (!NT_SUCCESS(status)) {
6160 ks_put_tconn(backlog);
6162 cfs_enter_debugger();
6166 /* associate it now ... */
6167 status = KsAssociateAddress(
6168 backlog->kstc_addr.Handle,
6169 backlog->child.kstc_info.FileObject
6172 if (!NT_SUCCESS(status)) {
6174 ks_put_tconn(backlog);
6176 cfs_enter_debugger();
6180 backlog->kstc_state = ksts_associated;
6188 * ks_replenish_backlogs(
6189 * to replenish the backlogs listening...
6192 * tconn: the parent listen tdi connect
6193 * nbacklog: number fo child connections in queue
6203 ks_replenish_backlogs(
6204 ksock_tconn_t * parent,
6208 ksock_tconn_t * backlog;
6211 /* calculate how many backlogs needed */
6212 if ( ( parent->listener.kstc_listening.num +
6213 parent->listener.kstc_accepted.num ) < nbacklog ) {
6214 n = nbacklog - ( parent->listener.kstc_listening.num +
6215 parent->listener.kstc_accepted.num );
6222 /* create the backlog child tconn */
6223 backlog = ks_create_child_tconn(parent);
6225 spin_lock(&(parent->kstc_lock));
6228 spin_lock(&backlog->kstc_lock);
6229 /* attch it into the listing list of daemon */
6230 list_add( &backlog->child.kstc_link,
6231 &parent->listener.kstc_listening.list );
6232 parent->listener.kstc_listening.num++;
6234 backlog->child.kstc_queued = TRUE;
6235 spin_unlock(&backlog->kstc_lock);
6237 cfs_enter_debugger();
6240 spin_unlock(&(parent->kstc_lock));
6246 * setup the listener tdi connection and make it listen
6247 * on the user specified ip address and port.
6250 * tconn: the parent listen tdi connect
6251 * nbacklog: number fo child connections in queue
6254 * ks error code >=: success; otherwise error.
6261 ks_start_listen(ksock_tconn_t *tconn, int nbacklog)
6265 /* now replenish the backlogs */
6266 ks_replenish_backlogs(tconn, nbacklog);
6268 /* set the event callback handlers */
6269 rc = ks_set_handlers(tconn);
6275 spin_lock(&(tconn->kstc_lock));
6276 tconn->listener.nbacklog = nbacklog;
6277 tconn->kstc_state = ksts_listening;
6278 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
6279 spin_unlock(&(tconn->kstc_lock));
6285 ks_stop_listen(ksock_tconn_t *tconn)
6287 struct list_head * list;
6288 ksock_tconn_t * backlog;
6290 /* reset all tdi event callbacks to NULL */
6291 ks_reset_handlers (tconn);
6293 spin_lock(&tconn->kstc_lock);
6295 cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
6297 /* cleanup all the listening backlog child connections */
6298 list_for_each (list, &(tconn->listener.kstc_listening.list)) {
6299 backlog = list_entry(list, ksock_tconn_t, child.kstc_link);
6301 /* destory and free it */
6302 ks_put_tconn(backlog);
6305 spin_unlock(&tconn->kstc_lock);
6307 /* wake up it from the waiting on new incoming connections */
6308 KeSetEvent(&tconn->listener.kstc_accept_event, 0, FALSE);
6310 /* free the listening daemon tconn */
6311 ks_put_tconn(tconn);
6316 * ks_wait_child_tconn
6317 * accept a child connection from peer
6320 * parent: the daemon tdi connection listening
6321 * child: to contain the accepted connection
6331 ks_wait_child_tconn(
6332 ksock_tconn_t * parent,
6333 ksock_tconn_t ** child
6336 struct list_head * tmp;
6337 ksock_tconn_t * backlog = NULL;
6339 ks_replenish_backlogs(parent, parent->listener.nbacklog);
6341 spin_lock(&(parent->kstc_lock));
6343 if (parent->listener.kstc_listening.num <= 0) {
6344 spin_unlock(&(parent->kstc_lock));
6350 /* check the listening queue and try to search the accepted connecton */
6352 list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
6353 backlog = list_entry (tmp, ksock_tconn_t, child.kstc_link);
6355 spin_lock(&(backlog->kstc_lock));
6357 if (backlog->child.kstc_accepted) {
6359 LASSERT(backlog->kstc_state == ksts_connected);
6360 LASSERT(backlog->child.kstc_busy);
6362 list_del(&(backlog->child.kstc_link));
6363 list_add(&(backlog->child.kstc_link),
6364 &(parent->listener.kstc_accepted.list));
6365 parent->listener.kstc_accepted.num++;
6366 parent->listener.kstc_listening.num--;
6367 backlog->child.kstc_queueno = 1;
6369 spin_unlock(&(backlog->kstc_lock));
6373 spin_unlock(&(backlog->kstc_lock));
6378 spin_unlock(&(parent->kstc_lock));
6380 /* we need wait until new incoming connections are requested
6381 or the case of shuting down the listenig daemon thread */
6382 if (backlog == NULL) {
6386 Status = KeWaitForSingleObject(
6387 &(parent->listener.kstc_accept_event),
6394 spin_lock(&(parent->kstc_lock));
6396 /* check whether it's exptected to exit ? */
6397 if (!cfs_is_flag_set(parent->kstc_flags, KS_TCONN_DAEMON_STARTED)) {
6398 spin_unlock(&(parent->kstc_lock));
6405 /* query the local ip address of the connection */
6406 ks_query_local_ipaddr(backlog);
6414 int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask)
6416 ks_addr_slot_t * slot = NULL;
6417 PLIST_ENTRY list = NULL;
6419 spin_lock(&ks_data.ksnd_addrs_lock);
6421 list = ks_data.ksnd_addrs_list.Flink;
6422 while (list != &ks_data.ksnd_addrs_list) {
6423 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
6424 if (_stricmp(name, &slot->iface[0]) == 0) {
6426 *ip = slot->ip_addr;
6427 *mask = slot->netmask;
6434 spin_unlock(&ks_data.ksnd_addrs_lock);
6436 return (int)(slot == NULL);
6439 int libcfs_ipif_enumerate(char ***names)
6441 ks_addr_slot_t * slot = NULL;
6442 PLIST_ENTRY list = NULL;
6445 spin_lock(&ks_data.ksnd_addrs_lock);
6447 *names = cfs_alloc(sizeof(char *) * ks_data.ksnd_naddrs, CFS_ALLOC_ZERO);
6448 if (*names == NULL) {
6452 list = ks_data.ksnd_addrs_list.Flink;
6453 while (list != &ks_data.ksnd_addrs_list) {
6454 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
6456 (*names)[nips++] = slot->iface;
6457 cfs_assert(nips <= ks_data.ksnd_naddrs);
6460 cfs_assert(nips == ks_data.ksnd_naddrs);
6464 spin_unlock(&ks_data.ksnd_addrs_lock);
6468 void libcfs_ipif_free_enumeration(char **names, int n)
6475 int libcfs_sock_listen(struct socket **sockp, __u32 ip, int port, int backlog)
6478 ksock_tconn_t * parent;
6480 parent = ks_create_tconn();
6486 /* initialize the tconn as a listener */
6487 ks_init_listener(parent);
6489 /* bind the daemon->tconn */
6490 rc = ks_bind_tconn(parent, NULL, ip, (unsigned short)port);
6493 ks_free_tconn(parent);
6497 /* create listening children and make it to listen state*/
6498 rc = ks_start_listen(parent, backlog);
6500 ks_stop_listen(parent);
6511 int libcfs_sock_accept(struct socket **newsockp, struct socket *sock)
6513 /* wait for incoming connecitons */
6514 return ks_wait_child_tconn(sock, newsockp);
6517 void libcfs_sock_abort_accept(struct socket *sock)
6519 LASSERT(sock->kstc_type == kstt_listener);
6521 spin_lock(&(sock->kstc_lock));
6523 /* clear the daemon flag */
6524 cfs_clear_flag(sock->kstc_flags, KS_TCONN_DAEMON_STARTED);
6526 /* wake up it from the waiting on new incoming connections */
6527 KeSetEvent(&sock->listener.kstc_accept_event, 0, FALSE);
6529 spin_unlock(&(sock->kstc_lock));
6533 * libcfs_sock_connect
6534 * build a conntion between local ip/port and the peer ip/port.
6537 * laddr: local ip address
6538 * lport: local port number
6539 * paddr: peer's ip address
6540 * pport: peer's port number
6543 * int: return code ...
6550 int libcfs_sock_connect(struct socket **sockp, int *fatal,
6551 __u32 local_ip, int local_port,
6552 __u32 peer_ip, int peer_port)
6554 ksock_tconn_t * tconn = NULL;
6559 KsPrint((1, "libcfs_sock_connect: connecting to %x:%d with %x:%d...\n",
6560 peer_ip, peer_port, local_ip, local_port ));
6562 /* create the tdi connecion structure */
6563 tconn = ks_create_tconn();
6569 /* initialize the tdi sender connection */
6570 ks_init_sender(tconn);
6572 /* bind the local ip address with the tconn */
6573 rc = ks_bind_tconn(tconn, NULL, local_ip, (unsigned short)local_port);
6575 KsPrint((0, "libcfs_sock_connect: failed to bind address %x:%d...\n",
6576 local_ip, local_port ));
6577 ks_free_tconn(tconn);
6581 /* connect to the remote peer */
6582 rc = ks_build_tconn(tconn, peer_ip, (unsigned short)peer_port);
6584 KsPrint((0, "libcfs_sock_connect: failed to connect %x:%d ...\n",
6585 peer_ip, peer_port ));
6587 ks_put_tconn(tconn);
6598 int libcfs_sock_setbuf(struct socket *socket, int txbufsize, int rxbufsize)
6603 int libcfs_sock_getbuf(struct socket *socket, int *txbufsize, int *rxbufsize)
6608 int libcfs_sock_getaddr(struct socket *socket, int remote, __u32 *ip, int *port)
6610 PTRANSPORT_ADDRESS taddr = NULL;
6612 spin_lock(&socket->kstc_lock);
6614 if (socket->kstc_type == kstt_sender) {
6615 taddr = socket->sender.kstc_info.Remote;
6616 } else if (socket->kstc_type == kstt_child) {
6617 taddr = socket->child.kstc_info.Remote;
6620 taddr = &(socket->kstc_addr.Tdi);
6624 PTDI_ADDRESS_IP addr = (PTDI_ADDRESS_IP)(&(taddr->Address[0].Address));
6626 *ip = ntohl (addr->in_addr);
6628 *port = ntohs (addr->sin_port);
6630 spin_unlock(&socket->kstc_lock);
6634 spin_unlock(&socket->kstc_lock);
6638 int libcfs_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
6645 while (nob > offset) {
6647 /* lock the user buffer */
6648 rc = ks_lock_buffer( (char *)buffer + offset,
6649 FALSE, nob - offset, IoReadAccess, &mdl );
6655 /* send out the whole mdl */
6656 rc = ks_send_mdl( sock, NULL, mdl, nob - offset, 0 );
6668 int libcfs_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
6675 while (nob > offset) {
6677 /* lock the user buffer */
6678 rc = ks_lock_buffer( (char *)buffer + offset,
6679 FALSE, nob - offset, IoWriteAccess, &mdl );
6685 /* recv the requested buffer */
6686 rc = ks_recv_mdl( sock, mdl, nob - offset, 0 );
6698 void libcfs_sock_release(struct socket *sock)
6700 if (sock->kstc_type == kstt_listener &&
6701 sock->kstc_state == ksts_listening) {
6702 ks_stop_listen(sock);