1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #define DEBUG_SUBSYSTEM S_LIBCFS
39 #include <libcfs/libcfs.h>
40 #include <lnet/lnet.h>
42 #define TDILND_MODULE_NAME L"Tdilnd"
47 ks_tdi_send_flags(ULONG SockFlags)
51 if (cfs_is_flag_set(SockFlags, MSG_OOB)) {
52 cfs_set_flag(TdiFlags, TDI_SEND_EXPEDITED);
55 if (cfs_is_flag_set(SockFlags, MSG_MORE)) {
56 cfs_set_flag(TdiFlags, TDI_SEND_PARTIAL);
59 if (cfs_is_flag_set(SockFlags, MSG_DONTWAIT)) {
60 cfs_set_flag(TdiFlags, TDI_SEND_NON_BLOCKING);
67 KsIrpCompletionRoutine(
68 IN PDEVICE_OBJECT DeviceObject,
73 if (NULL != Context) {
74 KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
77 return STATUS_MORE_PROCESSING_REQUIRED;
79 UNREFERENCED_PARAMETER(DeviceObject);
80 UNREFERENCED_PARAMETER(Irp);
86 * Allocate a new IRP and initialize it to be issued to tdi
89 * DeviceObject: device object created by the underlying
90 * TDI transport driver
93 * PRIP: the allocated Irp in success or NULL in failure.
101 IN PDEVICE_OBJECT DeviceObject
105 PIO_STACK_LOCATION IrpSp;
108 // Allocating the IRP ...
111 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
116 // Getting the Next Stack Location ...
119 IrpSp = IoGetNextIrpStackLocation(Irp);
122 // Initializing Irp ...
125 IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
126 IrpSp->Parameters.DeviceIoControl.IoControlCode = 0;
134 * Issue the Irp to the underlying tdi driver
137 * DeviceObject: the device object created by TDI driver
138 * Irp: the I/O request packet to be processed
139 * bSynchronous: synchronous or not. If true, we need wait
140 * until the process is finished.
141 * Information: returned info
144 * NTSTATUS: kernel status code
152 IN PDEVICE_OBJECT DeviceObject,
154 IN BOOLEAN bSynchronous,
155 OUT PULONG Information
165 SynchronizationEvent,
170 IoSetCompletionRoutine(
172 KsIrpCompletionRoutine,
180 Status = IoCallDriver(DeviceObject, Irp);
184 if (STATUS_PENDING == Status) {
186 Status = KeWaitForSingleObject(
195 Status = Irp->IoStatus.Status;
198 *Information = (ULONG)(Irp->IoStatus.Information);
201 Irp->MdlAddress = NULL;
205 if (!NT_SUCCESS(Status)) {
207 KsPrint((2, "KsSubmitTdiIrp: Error when submitting the Irp: Status = %xh (%s) ...\n",
208 Status, KsNtStatusToString(Status)));
218 * Open the Control Channel Object ...
221 * DeviceName: the device name to be opened
222 * Handle: opened handle in success case
223 * FileObject: the fileobject of the device
226 * NTSTATUS: kernel status code (STATUS_SUCCESS
227 * or other error code)
235 IN PUNICODE_STRING DeviceName,
237 OUT PFILE_OBJECT * FileObject
240 NTSTATUS Status = STATUS_SUCCESS;
242 OBJECT_ATTRIBUTES ObjectAttributes;
243 IO_STATUS_BLOCK IoStatus;
246 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
252 InitializeObjectAttributes(
255 OBJ_CASE_INSENSITIVE |
261 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
264 // Creating the Transport Address Object ...
267 Status = ZwCreateFile(
269 FILE_READ_DATA | FILE_WRITE_DATA,
273 FILE_ATTRIBUTE_NORMAL,
274 FILE_SHARE_READ | FILE_SHARE_WRITE,
282 if (NT_SUCCESS(Status)) {
285 // Now Obtaining the FileObject of the Transport Address ...
288 Status = ObReferenceObjectByHandle(
297 if (!NT_SUCCESS(Status)) {
299 cfs_enter_debugger();
305 cfs_enter_debugger();
314 * Release the Control Channel Handle and FileObject
317 * Handle: the channel handle to be released
318 * FileObject: the fileobject to be released
321 * NTSTATUS: kernel status code (STATUS_SUCCESS
322 * or other error code)
331 IN PFILE_OBJECT FileObject
334 NTSTATUS Status = STATUS_SUCCESS;
336 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
340 ObDereferenceObject(FileObject);
345 Status = ZwClose(Handle);
348 ASSERT(NT_SUCCESS(Status));
356 * Open the tdi address object
359 * DeviceName: device name of the address object
360 * pAddress: tdi address of the address object
361 * AddressLength: length in bytes of the tdi address
362 * Handle: the newly opened handle
363 * FileObject: the newly opened fileobject
366 * NTSTATUS: kernel status code (STATUS_SUCCESS
367 * or other error code)
375 IN PUNICODE_STRING DeviceName,
376 IN PTRANSPORT_ADDRESS pAddress,
377 IN ULONG AddressLength,
379 OUT PFILE_OBJECT * FileObject
382 NTSTATUS Status = STATUS_SUCCESS;
384 PFILE_FULL_EA_INFORMATION Ea = NULL;
386 UCHAR EaBuffer[EA_MAX_LENGTH];
388 OBJECT_ATTRIBUTES ObjectAttributes;
389 IO_STATUS_BLOCK IoStatus;
392 // Building EA for the Address Object to be Opened ...
395 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
396 Ea->NextEntryOffset = 0;
398 Ea->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
399 Ea->EaValueLength = (USHORT)AddressLength;
406 &(Ea->EaName[Ea->EaNameLength + 1]),
410 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
411 Ea->EaNameLength + AddressLength;
413 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
420 InitializeObjectAttributes(
423 OBJ_CASE_INSENSITIVE |
429 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
432 // Creating the Transport Address Object ...
435 Status = ZwCreateFile(
437 FILE_READ_DATA | FILE_WRITE_DATA,
441 FILE_ATTRIBUTE_NORMAL,
442 FILE_SHARE_READ | FILE_SHARE_WRITE, /* 0: DON'T REUSE */
450 if (NT_SUCCESS(Status)) {
453 // Now Obtaining the FileObject of the Transport Address ...
456 Status = ObReferenceObjectByHandle(
465 if (!NT_SUCCESS(Status)) {
467 cfs_enter_debugger();
473 cfs_enter_debugger();
481 * Release the Hanlde and FileObject of an opened tdi
485 * Handle: the handle to be released
486 * FileObject: the fileobject to be released
489 * NTSTATUS: kernel status code (STATUS_SUCCESS
490 * or other error code)
499 IN PFILE_OBJECT FileObject
502 NTSTATUS Status = STATUS_SUCCESS;
506 ObDereferenceObject(FileObject);
511 Status = ZwClose(Handle);
514 ASSERT(NT_SUCCESS(Status));
522 * Open a tdi connection object
525 * DeviceName: device name of the connection object
526 * ConnectionContext: the connection context
527 * Handle: the newly opened handle
528 * FileObject: the newly opened fileobject
531 * NTSTATUS: kernel status code (STATUS_SUCCESS
532 * or other error code)
540 IN PUNICODE_STRING DeviceName,
541 IN CONNECTION_CONTEXT ConnectionContext,
543 OUT PFILE_OBJECT * FileObject
546 NTSTATUS Status = STATUS_SUCCESS;
548 PFILE_FULL_EA_INFORMATION Ea = NULL;
550 UCHAR EaBuffer[EA_MAX_LENGTH];
552 OBJECT_ATTRIBUTES ObjectAttributes;
553 IO_STATUS_BLOCK IoStatus;
556 // Building EA for the Address Object to be Opened ...
559 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
560 Ea->NextEntryOffset = 0;
562 Ea->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
563 Ea->EaValueLength = (USHORT)sizeof(CONNECTION_CONTEXT);
566 TdiConnectionContext,
570 &(Ea->EaName[Ea->EaNameLength + 1]),
572 sizeof(CONNECTION_CONTEXT)
574 EaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
575 Ea->EaNameLength + 1 + sizeof(CONNECTION_CONTEXT);
577 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
584 InitializeObjectAttributes(
587 OBJ_CASE_INSENSITIVE |
593 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
596 // Creating the Connection Object ...
599 Status = ZwCreateFile(
601 FILE_READ_DATA | FILE_WRITE_DATA,
605 FILE_ATTRIBUTE_NORMAL,
614 if (NT_SUCCESS(Status)) {
617 // Now Obtaining the FileObject of the Transport Address ...
620 Status = ObReferenceObjectByHandle(
629 if (!NT_SUCCESS(Status)) {
631 cfs_enter_debugger();
637 cfs_enter_debugger();
645 * Release the Hanlde and FileObject of an opened tdi
649 * Handle: the handle to be released
650 * FileObject: the fileobject to be released
653 * NTSTATUS: kernel status code (STATUS_SUCCESS
654 * or other error code)
663 IN PFILE_OBJECT FileObject
666 NTSTATUS Status = STATUS_SUCCESS;
670 ObDereferenceObject(FileObject);
675 Status = ZwClose(Handle);
678 ASSERT(NT_SUCCESS(Status));
686 * Associate an address object with a connection object
689 * AddressHandle: the handle of the address object
690 * ConnectionObject: the FileObject of the connection
693 * NTSTATUS: kernel status code (STATUS_SUCCESS
694 * or other error code)
702 IN HANDLE AddressHandle,
703 IN PFILE_OBJECT ConnectionObject
707 PDEVICE_OBJECT DeviceObject;
711 // Getting the DeviceObject from Connection FileObject
714 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
717 // Building Tdi Internal Irp ...
720 Irp = KsBuildTdiIrp(DeviceObject);
724 Status = STATUS_INSUFFICIENT_RESOURCES;
729 // Assocating the Address Object with the Connection Object
732 TdiBuildAssociateAddress(
742 // Calling the Transprot Driver with the Prepared Irp
745 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
753 * KsDisassociateAddress
754 * Disassociate the connection object (the relationship will
755 * the corresponding address object will be dismissed. )
758 * ConnectionObject: the FileObject of the connection
761 * NTSTATUS: kernel status code (STATUS_SUCCESS
762 * or other error code)
769 KsDisassociateAddress(
770 IN PFILE_OBJECT ConnectionObject
774 PDEVICE_OBJECT DeviceObject;
778 // Getting the DeviceObject from Connection FileObject
781 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
784 // Building Tdi Internal Irp ...
787 Irp = KsBuildTdiIrp(DeviceObject);
791 Status = STATUS_INSUFFICIENT_RESOURCES;
796 // Disassocating the Address Object with the Connection Object
799 TdiBuildDisassociateAddress(
808 // Calling the Transprot Driver with the Prepared Irp
811 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
821 // Connection Control Event Callbacks
829 // Tcp Event Callbacks
833 TDI_EVENT_RECEIVE_EXPEDITED
834 TDI_EVENT_CHAINED_RECEIVE
835 TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
838 // Udp Event Callbacks
841 TDI_EVENT_RECEIVE_DATAGRAM
842 TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
849 * Set the tdi event callbacks with an address object
852 * AddressObject: the FileObject of the address object
853 * EventContext: the parameter for the callbacks
854 * Handlers: the handlers indictor array
857 * NTSTATUS: kernel status code (STATUS_SUCCESS
858 * or other error code)
866 IN PFILE_OBJECT AddressObject, // Address File Object
867 IN PVOID EventContext, // Context for Handlers
868 IN PKS_EVENT_HANDLERS Handlers // Handlers Indictor
871 NTSTATUS Status = STATUS_SUCCESS;
872 PDEVICE_OBJECT DeviceObject;
875 DeviceObject = IoGetRelatedDeviceObject(AddressObject);
877 for (i=0; i < TDI_EVENT_MAXIMUM_HANDLER; i++) {
880 // Setup the tdi event callback handler if requested.
883 if (Handlers->IsActive[i]) {
888 // Building Tdi Internal Irp ...
891 Irp = KsBuildTdiIrp(DeviceObject);
895 Status = STATUS_INSUFFICIENT_RESOURCES;
900 // Building the Irp to set the Event Handler ...
903 TdiBuildSetEventHandler(
909 i, /* tdi event type */
910 Handlers->Handler[i], /* tdi event handler */
911 EventContext /* context for the handler */
915 // Calling the Transprot Driver with the Prepared Irp
918 Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
921 // tcp/ip tdi does not support these two event callbacks
924 if ((!NT_SUCCESS(Status)) && ( i == TDI_EVENT_SEND_POSSIBLE ||
925 i == TDI_EVENT_CHAINED_RECEIVE_EXPEDITED )) {
926 cfs_enter_debugger();
927 Status = STATUS_SUCCESS;
931 if (!NT_SUCCESS(Status)) {
932 cfs_enter_debugger();
941 if (!NT_SUCCESS(Status)) {
943 KsPrint((2, "KsSetEventHandlers: Error Status = %xh (%s)\n",
944 Status, KsNtStatusToString(Status) ));
954 * Query the address of the FileObject specified
957 * FileObject: the FileObject to be queried
958 * AddressInfo: buffer to contain the address info
959 * AddressSize: length of the AddressInfo buffer
962 * NTSTATUS: kernel status code (STATUS_SUCCESS
963 * or other error code)
971 PFILE_OBJECT FileObject,
972 PTDI_ADDRESS_INFO AddressInfo,
976 NTSTATUS Status = STATUS_UNSUCCESSFUL;
979 PDEVICE_OBJECT DeviceObject;
981 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
983 DeviceObject = IoGetRelatedDeviceObject(FileObject);
985 RtlZeroMemory(AddressInfo, *(AddressSize));
988 // Allocating the Tdi Setting Irp ...
991 Irp = KsBuildTdiIrp(DeviceObject);
995 Status = STATUS_INSUFFICIENT_RESOURCES;
1000 // Locking the User Buffer / Allocating a MDL for it
1003 Status = KsLockUserBuffer(
1011 if (!NT_SUCCESS(Status)) {
1020 LASSERT(NT_SUCCESS(Status));
1022 TdiBuildQueryInformation(
1028 TDI_QUERY_ADDRESS_INFO,
1032 Status = KsSubmitTdiIrp(
1039 KsReleaseMdl(Mdl, FALSE);
1042 if (!NT_SUCCESS(Status)) {
1044 cfs_enter_debugger();
1045 //TDI_BUFFER_OVERFLOW
1052 * KsQueryProviderInfo
1053 * Query the underlying transport device's information
1056 * TdiDeviceName: the transport device's name string
1057 * ProviderInfo: TDI_PROVIDER_INFO struncture
1060 * NTSTATUS: Nt system status code
1067 KsQueryProviderInfo(
1068 PWSTR TdiDeviceName,
1069 PTDI_PROVIDER_INFO ProviderInfo
1072 NTSTATUS Status = STATUS_SUCCESS;
1077 UNICODE_STRING ControlName;
1080 PFILE_OBJECT FileObject;
1081 PDEVICE_OBJECT DeviceObject;
1083 ULONG ProviderSize = 0;
1085 RtlInitUnicodeString(&ControlName, TdiDeviceName);
1088 // Open the Tdi Control Channel
1091 Status = KsOpenControl(
1097 if (!NT_SUCCESS(Status)) {
1099 KsPrint((2, "KsQueryProviderInfo: Fail to open the tdi control channel.\n"));
1104 // Obtain The Related Device Object
1107 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1109 ProviderSize = sizeof(TDI_PROVIDER_INFO);
1110 RtlZeroMemory(ProviderInfo, ProviderSize);
1113 // Allocating the Tdi Setting Irp ...
1116 Irp = KsBuildTdiIrp(DeviceObject);
1120 Status = STATUS_INSUFFICIENT_RESOURCES;
1125 // Locking the User Buffer / Allocating a MDL for it
1128 Status = KsLockUserBuffer(
1136 if (!NT_SUCCESS(Status)) {
1145 LASSERT(NT_SUCCESS(Status));
1147 TdiBuildQueryInformation(
1153 TDI_QUERY_PROVIDER_INFO,
1157 Status = KsSubmitTdiIrp(
1164 KsReleaseMdl(Mdl, FALSE);
1167 if (!NT_SUCCESS(Status)) {
1169 cfs_enter_debugger();
1170 //TDI_BUFFER_OVERFLOW
1173 KsCloseControl(Handle, FileObject);
1179 * KsQueryConnectionInfo
1180 * Query the connection info of the FileObject specified
1181 * (some statics data of the traffic)
1184 * FileObject: the FileObject to be queried
1185 * ConnectionInfo: buffer to contain the connection info
1186 * ConnectionSize: length of the ConnectionInfo buffer
1189 * NTSTATUS: kernel status code (STATUS_SUCCESS
1190 * or other error code)
1197 KsQueryConnectionInfo(
1198 PFILE_OBJECT ConnectionObject,
1199 PTDI_CONNECTION_INFO ConnectionInfo,
1200 PULONG ConnectionSize
1203 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1206 PDEVICE_OBJECT DeviceObject;
1208 LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
1210 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
1212 RtlZeroMemory(ConnectionInfo, *(ConnectionSize));
1215 // Allocating the Tdi Query Irp ...
1218 Irp = KsBuildTdiIrp(DeviceObject);
1222 Status = STATUS_INSUFFICIENT_RESOURCES;
1227 // Locking the User Buffer / Allocating a MDL for it
1230 Status = KsLockUserBuffer(
1238 if (NT_SUCCESS(Status)) {
1247 LASSERT(NT_SUCCESS(Status));
1249 TdiBuildQueryInformation(
1255 TDI_QUERY_CONNECTION_INFO,
1259 Status = KsSubmitTdiIrp(
1266 KsReleaseMdl(Mdl, FALSE);
1274 * KsInitializeTdiAddress
1275 * Initialize the tdi addresss
1278 * pTransportAddress: tdi address to be initialized
1279 * IpAddress: the ip address of object
1280 * IpPort: the ip port of the object
1283 * ULONG: the total size of the tdi address
1290 KsInitializeTdiAddress(
1291 IN OUT PTA_IP_ADDRESS pTransportAddress,
1296 pTransportAddress->TAAddressCount = 1;
1297 pTransportAddress->Address[ 0 ].AddressLength = TDI_ADDRESS_LENGTH_IP;
1298 pTransportAddress->Address[ 0 ].AddressType = TDI_ADDRESS_TYPE_IP;
1299 pTransportAddress->Address[ 0 ].Address[ 0 ].sin_port = IpPort;
1300 pTransportAddress->Address[ 0 ].Address[ 0 ].in_addr = IpAddress;
1302 return (FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) + TDI_ADDRESS_LENGTH_IP);
1306 * KsQueryTdiAddressLength
1307 * Query the total size of the tdi address
1310 * pTransportAddress: tdi address to be queried
1313 * ULONG: the total size of the tdi address
1320 KsQueryTdiAddressLength(
1321 PTRANSPORT_ADDRESS pTransportAddress
1324 ULONG TotalLength = 0;
1327 PTA_ADDRESS UNALIGNED pTaAddress = NULL;
1329 ASSERT (NULL != pTransportAddress);
1331 TotalLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) +
1332 FIELD_OFFSET(TA_ADDRESS, Address) * pTransportAddress->TAAddressCount;
1334 pTaAddress = (TA_ADDRESS UNALIGNED *)pTransportAddress->Address;
1336 for (i = 0; i < pTransportAddress->TAAddressCount; i++)
1338 TotalLength += pTaAddress->AddressLength;
1339 pTaAddress = (TA_ADDRESS UNALIGNED *)((PCHAR)pTaAddress +
1340 FIELD_OFFSET(TA_ADDRESS,Address) +
1341 pTaAddress->AddressLength );
1344 return (TotalLength);
1350 * Query the ip address of the tdi object
1353 * FileObject: tdi object to be queried
1354 * TdiAddress: TdiAddress buffer, to store the queried
1356 * AddressLength: buffer length of the TdiAddress
1359 * ULONG: the total size of the tdi ip address
1367 PFILE_OBJECT FileObject,
1369 ULONG* AddressLength
1374 PTDI_ADDRESS_INFO TdiAddressInfo;
1379 // Maximum length of TDI_ADDRESSS_INFO with one TRANSPORT_ADDRESS
1382 Length = MAX_ADDRESS_LENGTH;
1384 TdiAddressInfo = (PTDI_ADDRESS_INFO)
1385 ExAllocatePoolWithTag(
1390 if (NULL == TdiAddressInfo) {
1392 Status = STATUS_INSUFFICIENT_RESOURCES;
1397 Status = KsQueryAddressInfo(
1405 if (NT_SUCCESS(Status))
1407 if (*AddressLength < Length) {
1409 Status = STATUS_BUFFER_TOO_SMALL;
1413 *AddressLength = Length;
1416 &(TdiAddressInfo->Address),
1420 Status = STATUS_SUCCESS;
1428 if (NULL != TdiAddressInfo) {
1430 ExFreePool(TdiAddressInfo);
1438 * KsErrorEventHandler
1439 * the common error event handler callback
1442 * TdiEventContext: should be the socket
1443 * Status: the error code
1446 * Status: STATS_SUCCESS
1449 * We need not do anything in such a severe
1450 * error case. System will process it for us.
1454 KsErrorEventHandler(
1455 IN PVOID TdiEventContext,
1459 KsPrint((2, "KsErrorEventHandler called at Irql = %xh ...\n",
1460 KeGetCurrentIrql()));
1462 cfs_enter_debugger();
1464 return (STATUS_SUCCESS);
1470 * setup all the event handler callbacks
1473 * tconn: the tdi connecton object
1476 * int: ks error code
1484 ksock_tconn_t * tconn
1487 NTSTATUS status = STATUS_SUCCESS;
1488 KS_EVENT_HANDLERS handlers;
1490 /* to make sure the address object is opened already */
1491 if (tconn->kstc_addr.FileObject == NULL) {
1495 /* initialize the handlers indictor array. for sender and listenr,
1496 there are different set of callbacks. for child, we just return. */
1498 memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
1500 SetEventHandler(handlers, TDI_EVENT_ERROR, KsErrorEventHandler);
1501 SetEventHandler(handlers, TDI_EVENT_DISCONNECT, KsDisconnectEventHandler);
1502 SetEventHandler(handlers, TDI_EVENT_RECEIVE, KsTcpReceiveEventHandler);
1503 SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, KsTcpReceiveExpeditedEventHandler);
1504 SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, KsTcpChainedReceiveEventHandler);
1506 // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, KsTcpChainedReceiveExpeditedEventHandler);
1508 if (tconn->kstc_type == kstt_listener) {
1509 SetEventHandler(handlers, TDI_EVENT_CONNECT, KsConnectEventHandler);
1510 } else if (tconn->kstc_type == kstt_child) {
1514 /* set all the event callbacks */
1515 status = KsSetEventHandlers(
1516 tconn->kstc_addr.FileObject, /* Address File Object */
1517 tconn, /* Event Context */
1518 &handlers /* Event callback handlers */
1523 return cfs_error_code(status);
1529 * disable all the event handler callbacks (set to NULL)
1532 * tconn: the tdi connecton object
1535 * int: ks error code
1543 ksock_tconn_t * tconn
1546 NTSTATUS status = STATUS_SUCCESS;
1547 KS_EVENT_HANDLERS handlers;
1549 /* to make sure the address object is opened already */
1550 if (tconn->kstc_addr.FileObject == NULL) {
1554 /* initialize the handlers indictor array. for sender and listenr,
1555 there are different set of callbacks. for child, we just return. */
1557 memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
1559 SetEventHandler(handlers, TDI_EVENT_ERROR, NULL);
1560 SetEventHandler(handlers, TDI_EVENT_DISCONNECT, NULL);
1561 SetEventHandler(handlers, TDI_EVENT_RECEIVE, NULL);
1562 SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, NULL);
1563 SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, NULL);
1564 // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, NULL);
1566 if (tconn->kstc_type == kstt_listener) {
1567 SetEventHandler(handlers, TDI_EVENT_CONNECT, NULL);
1568 } else if (tconn->kstc_type == kstt_child) {
1572 /* set all the event callbacks */
1573 status = KsSetEventHandlers(
1574 tconn->kstc_addr.FileObject, /* Address File Object */
1575 tconn, /* Event Context */
1576 &handlers /* Event callback handlers */
1581 return cfs_error_code(status);
1586 * KsAcceptCompletionRoutine
1587 * Irp completion routine for TdiBuildAccept (KsConnectEventHandler)
1589 * Here system gives us a chance to check the conneciton is built
1593 * DeviceObject: the device object of the transport driver
1594 * Irp: the Irp is being completed.
1595 * Context: the context we specified when issuing the Irp
1605 KsAcceptCompletionRoutine(
1606 IN PDEVICE_OBJECT DeviceObject,
1611 ksock_tconn_t * child = (ksock_tconn_t *) Context;
1612 ksock_tconn_t * parent = child->child.kstc_parent;
1614 KsPrint((2, "KsAcceptCompletionRoutine: called at Irql: %xh\n",
1615 KeGetCurrentIrql() ));
1617 KsPrint((2, "KsAcceptCompletionRoutine: Context = %xh Status = %xh\n",
1618 Context, Irp->IoStatus.Status));
1620 LASSERT(child->kstc_type == kstt_child);
1622 spin_lock(&(child->kstc_lock));
1624 LASSERT(parent->kstc_state == ksts_listening);
1625 LASSERT(child->kstc_state == ksts_connecting);
1627 if (NT_SUCCESS(Irp->IoStatus.Status)) {
1629 child->child.kstc_accepted = TRUE;
1631 child->kstc_state = ksts_connected;
1633 /* wake up the daemon thread which waits on this event */
1635 &(parent->listener.kstc_accept_event),
1640 spin_unlock(&(child->kstc_lock));
1642 KsPrint((2, "KsAcceptCompletionRoutine: Get %xh now signal the event ...\n", parent));
1646 /* re-use this child connecton */
1647 child->child.kstc_accepted = FALSE;
1648 child->child.kstc_busy = FALSE;
1649 child->kstc_state = ksts_associated;
1651 spin_unlock(&(child->kstc_lock));
1654 /* now free the Irp */
1657 /* drop the refer count of the child */
1658 ks_put_tconn(child);
1660 return (STATUS_MORE_PROCESSING_REQUIRED);
1665 * ks_get_vacancy_backlog
1666 * Get a vacancy listeing child from the backlog list
1669 * parent: the listener daemon connection
1672 * the child listening connection or NULL in failure
1675 * Parent's lock should be acquired before calling.
1679 ks_get_vacancy_backlog(
1680 ksock_tconn_t * parent
1683 ksock_tconn_t * child;
1685 LASSERT(parent->kstc_type == kstt_listener);
1686 LASSERT(parent->kstc_state == ksts_listening);
1688 if (list_empty(&(parent->listener.kstc_listening.list))) {
1694 struct list_head * tmp;
1696 /* check the listening queue and try to get a free connecton */
1698 list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
1699 child = list_entry (tmp, ksock_tconn_t, child.kstc_link);
1700 spin_lock(&(child->kstc_lock));
1702 if (!child->child.kstc_busy) {
1703 LASSERT(child->kstc_state == ksts_associated);
1704 child->child.kstc_busy = TRUE;
1705 spin_unlock(&(child->kstc_lock));
1708 spin_unlock(&(child->kstc_lock));
1718 KsSearchIpAddress(PUNICODE_STRING DeviceName)
1720 ks_addr_slot_t * slot = NULL;
1721 PLIST_ENTRY list = NULL;
1723 spin_lock(&ks_data.ksnd_addrs_lock);
1725 list = ks_data.ksnd_addrs_list.Flink;
1726 while (list != &ks_data.ksnd_addrs_list) {
1727 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
1728 if (RtlCompareUnicodeString(
1738 spin_unlock(&ks_data.ksnd_addrs_lock);
1744 KsCleanupIpAddresses()
1746 spin_lock(&ks_data.ksnd_addrs_lock);
1748 while (!IsListEmpty(&ks_data.ksnd_addrs_list)) {
1750 ks_addr_slot_t * slot = NULL;
1751 PLIST_ENTRY list = NULL;
1753 list = RemoveHeadList(&ks_data.ksnd_addrs_list);
1754 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
1756 ks_data.ksnd_naddrs--;
1759 cfs_assert(ks_data.ksnd_naddrs == 0);
1760 spin_unlock(&ks_data.ksnd_addrs_lock);
1764 KsAddAddressHandler(
1765 IN PTA_ADDRESS Address,
1766 IN PUNICODE_STRING DeviceName,
1767 IN PTDI_PNP_CONTEXT Context
1770 PTDI_ADDRESS_IP IpAddress = NULL;
1772 if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
1773 Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
1775 ks_addr_slot_t * slot = NULL;
1777 IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
1778 KsPrint((1, "KsAddAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
1779 DeviceName, Context, IpAddress->in_addr,
1780 (IpAddress->in_addr & 0xFF000000) >> 24,
1781 (IpAddress->in_addr & 0x00FF0000) >> 16,
1782 (IpAddress->in_addr & 0x0000FF00) >> 8,
1783 (IpAddress->in_addr & 0x000000FF) >> 0 ));
1785 slot = KsSearchIpAddress(DeviceName);
1789 slot->ip_addr = ntohl(IpAddress->in_addr);
1791 slot = cfs_alloc(sizeof(ks_addr_slot_t) + DeviceName->Length, CFS_ALLOC_ZERO);
1793 spin_lock(&ks_data.ksnd_addrs_lock);
1794 InsertTailList(&ks_data.ksnd_addrs_list, &slot->link);
1795 sprintf(slot->iface, "eth%d", ks_data.ksnd_naddrs++);
1796 slot->ip_addr = ntohl(IpAddress->in_addr);
1798 RtlMoveMemory(&slot->buffer[0], DeviceName->Buffer, DeviceName->Length);
1799 slot->devname.Length = DeviceName->Length;
1800 slot->devname.MaximumLength = DeviceName->Length + sizeof(WCHAR);
1801 slot->devname.Buffer = slot->buffer;
1802 spin_unlock(&ks_data.ksnd_addrs_lock);
1809 KsDelAddressHandler(
1810 IN PTA_ADDRESS Address,
1811 IN PUNICODE_STRING DeviceName,
1812 IN PTDI_PNP_CONTEXT Context
1815 PTDI_ADDRESS_IP IpAddress = NULL;
1817 if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
1818 Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
1820 ks_addr_slot_t * slot = NULL;
1822 slot = KsSearchIpAddress(DeviceName);
1828 IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
1829 KsPrint((1, "KsDelAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
1830 DeviceName, Context, IpAddress->in_addr,
1831 (IpAddress->in_addr & 0xFF000000) >> 24,
1832 (IpAddress->in_addr & 0x00FF0000) >> 16,
1833 (IpAddress->in_addr & 0x0000FF00) >> 8,
1834 (IpAddress->in_addr & 0x000000FF) >> 0 ));
1839 KsRegisterPnpHandlers()
1841 TDI20_CLIENT_INTERFACE_INFO ClientInfo;
1843 /* initialize the global ks_data members */
1844 RtlInitUnicodeString(&ks_data.ksnd_client_name, TDILND_MODULE_NAME);
1845 spin_lock_init(&ks_data.ksnd_addrs_lock);
1846 InitializeListHead(&ks_data.ksnd_addrs_list);
1848 /* register the pnp handlers */
1849 RtlZeroMemory(&ClientInfo, sizeof(ClientInfo));
1850 ClientInfo.TdiVersion = TDI_CURRENT_VERSION;
1852 ClientInfo.ClientName = &ks_data.ksnd_client_name;
1853 ClientInfo.AddAddressHandlerV2 = KsAddAddressHandler;
1854 ClientInfo.DelAddressHandlerV2 = KsDelAddressHandler;
1856 return TdiRegisterPnPHandlers(&ClientInfo, sizeof(ClientInfo),
1857 &ks_data.ksnd_pnp_handle);
1861 KsDeregisterPnpHandlers()
1863 if (ks_data.ksnd_pnp_handle) {
1865 /* De-register the pnp handlers */
1867 TdiDeregisterPnPHandlers(ks_data.ksnd_pnp_handle);
1868 ks_data.ksnd_pnp_handle = NULL;
1870 /* cleanup all the ip address slots */
1871 KsCleanupIpAddresses();
1876 * KsConnectEventHandler
1877 * Connect event handler event handler, called by the underlying TDI
1878 * transport in response to an incoming request to the listening daemon.
1880 * it will grab a vacancy backlog from the children tconn list, and
1881 * build an acception Irp with it, then transfer the Irp to TDI driver.
1884 * TdiEventContext: the tdi connnection object of the listening daemon
1888 * Nt kernel status code
1895 KsConnectEventHandler(
1896 IN PVOID TdiEventContext,
1897 IN LONG RemoteAddressLength,
1898 IN PVOID RemoteAddress,
1899 IN LONG UserDataLength,
1901 IN LONG OptionsLength,
1903 OUT CONNECTION_CONTEXT * ConnectionContext,
1904 OUT PIRP * AcceptIrp
1907 ksock_tconn_t * parent;
1908 ksock_tconn_t * child;
1910 PFILE_OBJECT FileObject;
1911 PDEVICE_OBJECT DeviceObject;
1915 PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
1917 KsPrint((2,"KsConnectEventHandler: call at Irql: %u\n", KeGetCurrentIrql()));
1918 parent = (ksock_tconn_t *) TdiEventContext;
1920 LASSERT(parent->kstc_type == kstt_listener);
1922 spin_lock(&(parent->kstc_lock));
1924 if (parent->kstc_state == ksts_listening) {
1926 /* allocate a new ConnectionInfo to backup the peer's info */
1928 ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
1929 NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) +
1930 RemoteAddressLength, 'iCsK' );
1932 if (NULL == ConnectionInfo) {
1934 Status = STATUS_INSUFFICIENT_RESOURCES;
1935 cfs_enter_debugger();
1939 /* initializing ConnectionInfo structure ... */
1941 ConnectionInfo->UserDataLength = UserDataLength;
1942 ConnectionInfo->UserData = UserData;
1943 ConnectionInfo->OptionsLength = OptionsLength;
1944 ConnectionInfo->Options = Options;
1945 ConnectionInfo->RemoteAddressLength = RemoteAddressLength;
1946 ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
1949 ConnectionInfo->RemoteAddress,
1954 /* get the vacancy listening child tdi connections */
1956 child = ks_get_vacancy_backlog(parent);
1960 spin_lock(&(child->kstc_lock));
1961 child->child.kstc_info.ConnectionInfo = ConnectionInfo;
1962 child->child.kstc_info.Remote = ConnectionInfo->RemoteAddress;
1963 child->kstc_state = ksts_connecting;
1964 spin_unlock(&(child->kstc_lock));
1968 KsPrint((2, "KsConnectEventHandler: No enough backlogs: Refsued the connectio: %xh\n", parent));
1970 Status = STATUS_INSUFFICIENT_RESOURCES;
1975 FileObject = child->child.kstc_info.FileObject;
1976 DeviceObject = IoGetRelatedDeviceObject (FileObject);
1978 Irp = KsBuildTdiIrp(DeviceObject);
1984 KsAcceptCompletionRoutine,
1990 IoSetNextIrpStackLocation(Irp);
1992 /* grap the refer of the child tdi connection */
1993 ks_get_tconn(child);
1995 Status = STATUS_MORE_PROCESSING_REQUIRED;
1998 *ConnectionContext = child;
2002 Status = STATUS_CONNECTION_REFUSED;
2006 spin_unlock(&(parent->kstc_lock));
2012 spin_unlock(&(parent->kstc_lock));
2016 *ConnectionContext = NULL;
2018 if (ConnectionInfo) {
2020 ExFreePool(ConnectionInfo);
2033 * KsDisconnectCompletionRoutine
2034 * the Irp completion routine for TdiBuildDisconect
2036 * We just signal the event and return MORE_PRO... to
2037 * let the caller take the responsibility of the Irp.
2040 * DeviceObject: the device object of the transport
2041 * Irp: the Irp is being completed.
2042 * Context: the event specified by the caller
2052 KsDisconectCompletionRoutine (
2053 IN PDEVICE_OBJECT DeviceObject,
2059 KeSetEvent((PKEVENT) Context, 0, FALSE);
2061 return STATUS_MORE_PROCESSING_REQUIRED;
2063 UNREFERENCED_PARAMETER(DeviceObject);
2068 * KsDisconnectHelper
2069 * the routine to be executed in the WorkItem procedure
2070 * this routine is to disconnect a tdi connection
2073 * Workitem: the context transferred to the workitem
2079 * tconn is already referred in abort_connecton ...
2083 KsDisconnectHelper(PKS_DISCONNECT_WORKITEM WorkItem)
2085 ksock_tconn_t * tconn = WorkItem->tconn;
2087 DbgPrint("KsDisconnectHelper: disconnecting tconn=%p\n", tconn);
2088 ks_disconnect_tconn(tconn, WorkItem->Flags);
2090 KeSetEvent(&(WorkItem->Event), 0, FALSE);
2092 spin_lock(&(tconn->kstc_lock));
2093 cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
2094 spin_unlock(&(tconn->kstc_lock));
2095 ks_put_tconn(tconn);
2100 * KsDisconnectEventHandler
2101 * Disconnect event handler event handler, called by the underlying TDI transport
2102 * in response to an incoming disconnection notification from a remote node.
2105 * ConnectionContext: tdi connnection object
2106 * DisconnectFlags: specifies the nature of the disconnection
2110 * Nt kernel status code
2118 KsDisconnectEventHandler(
2119 IN PVOID TdiEventContext,
2120 IN CONNECTION_CONTEXT ConnectionContext,
2121 IN LONG DisconnectDataLength,
2122 IN PVOID DisconnectData,
2123 IN LONG DisconnectInformationLength,
2124 IN PVOID DisconnectInformation,
2125 IN ULONG DisconnectFlags
2128 ksock_tconn_t * tconn;
2130 PKS_DISCONNECT_WORKITEM WorkItem;
2132 tconn = (ksock_tconn_t *)ConnectionContext;
2134 KsPrint((2, "KsTcpDisconnectEventHandler: called at Irql: %xh\n",
2135 KeGetCurrentIrql() ));
2137 KsPrint((2, "tconn = %x DisconnectFlags= %xh\n",
2138 tconn, DisconnectFlags));
2140 ks_get_tconn(tconn);
2141 spin_lock(&(tconn->kstc_lock));
2143 WorkItem = &(tconn->kstc_disconnect);
2145 if (tconn->kstc_state != ksts_connected) {
2147 Status = STATUS_SUCCESS;
2151 if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_ABORT)) {
2153 Status = STATUS_REMOTE_DISCONNECT;
2155 } else if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_RELEASE)) {
2157 Status = STATUS_GRACEFUL_DISCONNECT;
2160 if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
2162 ks_get_tconn(tconn);
2164 WorkItem->Flags = DisconnectFlags;
2165 WorkItem->tconn = tconn;
2167 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
2169 /* queue the workitem to call */
2170 ExQueueWorkItem(&(WorkItem->WorkItem), DelayedWorkQueue);
2174 spin_unlock(&(tconn->kstc_lock));
2175 ks_put_tconn(tconn);
2181 KsTcpReceiveCompletionRoutine(
2183 IN PKS_TCP_COMPLETION_CONTEXT Context
2186 NTSTATUS Status = Irp->IoStatus.Status;
2188 if (NT_SUCCESS(Status)) {
2190 ksock_tconn_t *tconn = Context->tconn;
2192 PKS_TSDU_DAT KsTsduDat = Context->CompletionContext;
2193 PKS_TSDU_BUF KsTsduBuf = Context->CompletionContext;
2195 KsPrint((1, "KsTcpReceiveCompletionRoutine: Total %xh bytes.\n",
2196 Context->KsTsduMgr->TotalBytes ));
2198 spin_lock(&(tconn->kstc_lock));
2200 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
2201 if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
2202 cfs_clear_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
2204 cfs_enter_debugger();
2207 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
2208 if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
2209 cfs_clear_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
2211 cfs_enter_debugger();
2215 spin_unlock(&(tconn->kstc_lock));
2217 /* wake up the thread waiting for the completion of this Irp */
2218 KeSetEvent(Context->Event, 0, FALSE);
2220 /* re-active the ks connection and wake up the scheduler */
2221 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2222 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2223 Context->KsTsduMgr->TotalBytes );
2228 /* un-expected errors occur, we must abort the connection */
2229 ks_abort_tconn(Context->tconn);
2234 /* Freeing the Context structure... */
2235 ExFreePool(Context);
2250 * KsTcpCompletionRoutine
2251 * the Irp completion routine for TdiBuildSend and TdiBuildReceive ...
2252 * We need call the use's own CompletionRoutine if specified. Or
2253 * it's a synchronous case, we need signal the event.
2256 * DeviceObject: the device object of the transport
2257 * Irp: the Irp is being completed.
2258 * Context: the context we specified when issuing the Irp
2268 KsTcpCompletionRoutine(
2269 IN PDEVICE_OBJECT DeviceObject,
2276 PKS_TCP_COMPLETION_CONTEXT CompletionContext = NULL;
2277 ksock_tconn_t * tconn = NULL;
2279 CompletionContext = (PKS_TCP_COMPLETION_CONTEXT) Context;
2280 tconn = CompletionContext->tconn;
2282 /* release the chained mdl */
2283 KsReleaseMdl(Irp->MdlAddress, FALSE);
2284 Irp->MdlAddress = NULL;
2286 if (CompletionContext->CompletionRoutine) {
2288 if ( CompletionContext->bCounted &&
2289 InterlockedDecrement(&CompletionContext->ReferCount) != 0 ) {
2294 // Giving control to user specified CompletionRoutine ...
2297 CompletionContext->CompletionRoutine(
2305 // Signaling the Event ...
2308 KeSetEvent(CompletionContext->Event, 0, FALSE);
2311 /* drop the reference count of the tconn object */
2312 ks_put_tconn(tconn);
2316 cfs_enter_debugger();
2321 return STATUS_MORE_PROCESSING_REQUIRED;
2325 * KsTcpSendCompletionRoutine
2326 * the user specified Irp completion routine for asynchronous
2327 * data transmission requests.
2329 * It will do th cleanup job of the ksock_tx_t and wake up the
2330 * ks scheduler thread
2333 * Irp: the Irp is being completed.
2334 * Context: the context we specified when issuing the Irp
2344 KsTcpSendCompletionRoutine(
2346 IN PKS_TCP_COMPLETION_CONTEXT Context
2349 NTSTATUS Status = Irp->IoStatus.Status;
2350 ULONG rc = Irp->IoStatus.Information;
2351 ksock_tconn_t * tconn = Context->tconn;
2352 PKS_TSDUMGR KsTsduMgr = Context->KsTsduMgr;
2358 if (NT_SUCCESS(Status)) {
2360 if (Context->bCounted) {
2361 PVOID tx = Context->CompletionContext;
2363 ASSERT(tconn->kstc_update_tx != NULL);
2365 /* update the tx, rebasing the kiov or iov pointers */
2366 tx = tconn->kstc_update_tx(tconn, tx, rc);
2368 /* update the KsTsudMgr total bytes */
2369 spin_lock(&tconn->kstc_lock);
2370 KsTsduMgr->TotalBytes -= rc;
2371 spin_unlock(&tconn->kstc_lock);
2374 * now it's time to re-queue the conns into the
2375 * scheduler queue and wake the scheduler thread.
2378 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2379 tconn->kstc_sched_cb( tconn, TRUE, tx, 0);
2384 PKS_TSDU KsTsdu = Context->CompletionContext;
2385 PKS_TSDU_BUF KsTsduBuf = Context->CompletionContext2;
2386 PKS_TSDU_DAT KsTsduDat = Context->CompletionContext2;
2388 spin_lock(&tconn->kstc_lock);
2389 /* This is bufferred sending ... */
2390 ASSERT(KsTsduBuf->StartOffset == 0);
2392 if (KsTsduBuf->DataLength > Irp->IoStatus.Information) {
2393 /* not fully sent .... we have to abort the connection */
2394 spin_unlock(&tconn->kstc_lock);
2395 ks_abort_tconn(tconn);
2399 if (KsTsduBuf->TsduType == TSDU_TYPE_BUF) {
2400 /* free the buffer */
2401 ExFreePool(KsTsduBuf->UserBuffer);
2402 KsTsduMgr->TotalBytes -= KsTsduBuf->DataLength;
2403 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
2404 } else if (KsTsduDat->TsduType == TSDU_TYPE_DAT) {
2405 KsTsduMgr->TotalBytes -= KsTsduDat->DataLength;
2406 KsTsdu->StartOffset += KsTsduDat->TotalLength;
2408 cfs_enter_debugger(); /* shoult not get here */
2411 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
2413 list_del(&KsTsdu->Link);
2414 KsTsduMgr->NumOfTsdu--;
2415 KsPutKsTsdu(KsTsdu);
2418 spin_unlock(&tconn->kstc_lock);
2423 /* cfs_enter_debugger(); */
2426 * for the case that the transmission is ussuccessful,
2427 * we need abort the tdi connection, but not destroy it.
2428 * the socknal conn will drop the refer count, then the
2429 * tdi connection will be freed.
2432 ks_abort_tconn(tconn);
2437 /* freeing the Context structure... */
2440 ExFreePool(Context);
2444 /* it's our duty to free the Irp. */
2457 * Normal receive event handler
2459 * It will move data from system Tsdu to our TsduList
2463 KsTcpReceiveEventHandler(
2464 IN PVOID TdiEventContext,
2465 IN CONNECTION_CONTEXT ConnectionContext,
2466 IN ULONG ReceiveFlags,
2467 IN ULONG BytesIndicated,
2468 IN ULONG BytesAvailable,
2469 OUT ULONG * BytesTaken,
2471 OUT PIRP * IoRequestPacket
2476 ksock_tconn_t * tconn;
2479 PKS_TSDUMGR KsTsduMgr;
2481 PKS_TSDU_DAT KsTsduDat;
2482 PKS_TSDU_BUF KsTsduBuf;
2484 BOOLEAN bIsExpedited;
2485 BOOLEAN bIsCompleteTsdu;
2487 BOOLEAN bNewTsdu = FALSE;
2488 BOOLEAN bNewBuff = FALSE;
2490 PCHAR Buffer = NULL;
2494 PFILE_OBJECT FileObject;
2495 PDEVICE_OBJECT DeviceObject;
2497 ULONG BytesReceived = 0;
2499 PKS_TCP_COMPLETION_CONTEXT context = NULL;
2502 tconn = (ksock_tconn_t *) ConnectionContext;
2504 ks_get_tconn(tconn);
2506 /* check whether the whole body of payload is received or not */
2507 if ( (cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_ENTIRE_MESSAGE)) &&
2508 (BytesIndicated == BytesAvailable) ) {
2509 bIsCompleteTsdu = TRUE;
2511 bIsCompleteTsdu = FALSE;
2514 bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
2516 KsPrint((2, "KsTcpReceiveEventHandler BytesIndicated = %d BytesAvailable = %d ...\n", BytesIndicated, BytesAvailable));
2517 KsPrint((2, "bIsCompleteTsdu = %d bIsExpedited = %d\n", bIsCompleteTsdu, bIsExpedited ));
2519 spin_lock(&(tconn->kstc_lock));
2521 /* check whether we are conntected or not listener ¡Â*/
2522 if ( !((tconn->kstc_state == ksts_connected) &&
2523 (tconn->kstc_type == kstt_sender ||
2524 tconn->kstc_type == kstt_child))) {
2526 *BytesTaken = BytesIndicated;
2528 spin_unlock(&(tconn->kstc_lock));
2529 ks_put_tconn(tconn);
2531 return (STATUS_SUCCESS);
2534 if (tconn->kstc_type == kstt_sender) {
2535 KsChain = &(tconn->sender.kstc_recv);
2537 LASSERT(tconn->kstc_type == kstt_child);
2538 KsChain = &(tconn->child.kstc_recv);
2542 KsTsduMgr = &(KsChain->Expedited);
2544 KsTsduMgr = &(KsChain->Normal);
2547 /* if the Tsdu is even larger than the biggest Tsdu, we have
2548 to allocate new buffer and use TSDU_TYOE_BUF to store it */
2550 if ( KS_TSDU_STRU_SIZE(BytesAvailable) > ks_data.ksnd_tsdu_size -
2551 KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
2555 /* retrieve the latest Tsdu buffer form TsduMgr
2556 list if the list is not empty. */
2558 if (list_empty(&(KsTsduMgr->TsduList))) {
2560 LASSERT(KsTsduMgr->NumOfTsdu == 0);
2565 LASSERT(KsTsduMgr->NumOfTsdu > 0);
2566 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
2568 /* if this Tsdu does not contain enough space, we need
2569 allocate a new Tsdu queue. */
2572 if ( KsTsdu->LastOffset + sizeof(KS_TSDU_BUF) >
2573 KsTsdu->TotalLength ) {
2577 if ( KS_TSDU_STRU_SIZE(BytesAvailable) >
2578 KsTsdu->TotalLength - KsTsdu->LastOffset ) {
2584 /* allocating the buffer for TSDU_TYPE_BUF */
2586 Buffer = ExAllocatePool(NonPagedPool, BytesAvailable);
2587 if (NULL == Buffer) {
2588 /* there's no enough memory for us. We just try to
2589 receive maximum bytes with a new Tsdu */
2595 /* allocate a new Tsdu in case we are not statisfied. */
2597 if (NULL == KsTsdu) {
2599 KsTsdu = KsAllocateKsTsdu();
2601 if (NULL == KsTsdu) {
2608 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2609 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2613 /* setup up the KS_TSDU_BUF record */
2615 KsTsduBuf->TsduType = TSDU_TYPE_BUF;
2616 KsTsduBuf->TsduFlags = 0;
2617 KsTsduBuf->StartOffset = 0;
2618 KsTsduBuf->UserBuffer = Buffer;
2619 KsTsduBuf->DataLength = BytesReceived = BytesAvailable;
2621 KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
2625 /* setup the KS_TSDU_DATA to contain all the messages */
2627 KsTsduDat->TsduType = TSDU_TYPE_DAT;
2628 KsTsduDat->TsduFlags = 0;
2630 if ( KsTsdu->TotalLength - KsTsdu->LastOffset >=
2631 KS_TSDU_STRU_SIZE(BytesAvailable) ) {
2632 BytesReceived = BytesAvailable;
2634 BytesReceived = KsTsdu->TotalLength - KsTsdu->LastOffset -
2635 FIELD_OFFSET(KS_TSDU_DAT, Data);
2636 BytesReceived &= (~((ULONG)3));
2638 KsTsduDat->DataLength = BytesReceived;
2639 KsTsduDat->TotalLength = KS_TSDU_STRU_SIZE(BytesReceived);
2640 KsTsduDat->StartOffset = 0;
2642 Buffer = &KsTsduDat->Data[0];
2644 KsTsdu->LastOffset += KsTsduDat->TotalLength;
2647 KsTsduMgr->TotalBytes += BytesReceived;
2649 if (bIsCompleteTsdu) {
2651 /* It's a complete receive, we just move all
2652 the data from system to our Tsdu */
2660 *BytesTaken = BytesReceived;
2661 Status = STATUS_SUCCESS;
2664 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2665 KsTsduMgr->NumOfTsdu++;
2668 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
2670 /* re-active the ks connection and wake up the scheduler */
2671 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2672 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2673 KsTsduMgr->TotalBytes );
2678 /* there's still data in tdi internal queue, we need issue a new
2679 Irp to receive all of them. first allocate the tcp context */
2681 context = ExAllocatePoolWithTag(
2683 sizeof(KS_TCP_COMPLETION_CONTEXT),
2688 Status = STATUS_INSUFFICIENT_RESOURCES;
2692 /* setup the context */
2693 RtlZeroMemory(context, sizeof(KS_TCP_COMPLETION_CONTEXT));
2695 context->tconn = tconn;
2696 context->CompletionRoutine = KsTcpReceiveCompletionRoutine;
2697 context->CompletionContext = KsTsdu;
2698 context->CompletionContext = bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat;
2699 context->KsTsduMgr = KsTsduMgr;
2700 context->Event = &(KsTsduMgr->Event);
2702 if (tconn->kstc_type == kstt_sender) {
2703 FileObject = tconn->sender.kstc_info.FileObject;
2705 FileObject = tconn->child.kstc_info.FileObject;
2708 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2710 /* build new tdi Irp and setup it. */
2711 Irp = KsBuildTdiIrp(DeviceObject);
2717 Status = KsLockUserBuffer(
2725 if (!NT_SUCCESS(Status)) {
2733 KsTcpCompletionRoutine,
2736 ReceiveFlags & (TDI_RECEIVE_NORMAL | TDI_RECEIVE_EXPEDITED),
2740 IoSetNextIrpStackLocation(Irp);
2742 /* return the newly built Irp to transport driver,
2743 it will process it to receive all the data */
2745 *IoRequestPacket = Irp;
2750 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2751 KsTsduMgr->NumOfTsdu++;
2755 cfs_set_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
2757 cfs_set_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
2759 ks_get_tconn(tconn);
2760 Status = STATUS_MORE_PROCESSING_REQUIRED;
2763 spin_unlock(&(tconn->kstc_lock));
2764 ks_put_tconn(tconn);
2770 spin_unlock(&(tconn->kstc_lock));
2772 if (bNewTsdu && (KsTsdu != NULL)) {
2773 KsFreeKsTsdu(KsTsdu);
2777 KsReleaseMdl(Mdl, FALSE);
2785 ExFreePool(context);
2788 ks_abort_tconn(tconn);
2789 ks_put_tconn(tconn);
2791 *BytesTaken = BytesAvailable;
2792 Status = STATUS_SUCCESS;
2798 * Expedited receive event handler
2802 KsTcpReceiveExpeditedEventHandler(
2803 IN PVOID TdiEventContext,
2804 IN CONNECTION_CONTEXT ConnectionContext,
2805 IN ULONG ReceiveFlags,
2806 IN ULONG BytesIndicated,
2807 IN ULONG BytesAvailable,
2808 OUT ULONG * BytesTaken,
2810 OUT PIRP * IoRequestPacket
2813 return KsTcpReceiveEventHandler(
2816 ReceiveFlags | TDI_RECEIVE_EXPEDITED,
2827 * Bulk receive event handler
2829 * It will queue all the system Tsdus to our TsduList.
2830 * Then later ks_recv_mdl will release them.
2834 KsTcpChainedReceiveEventHandler (
2835 IN PVOID TdiEventContext, // the event context
2836 IN CONNECTION_CONTEXT ConnectionContext,
2837 IN ULONG ReceiveFlags,
2838 IN ULONG ReceiveLength,
2839 IN ULONG StartingOffset, // offset of start of client data in TSDU
2840 IN PMDL Tsdu, // TSDU data chain
2841 IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives
2847 ksock_tconn_t * tconn;
2850 PKS_TSDUMGR KsTsduMgr;
2852 PKS_TSDU_MDL KsTsduMdl;
2854 BOOLEAN bIsExpedited;
2855 BOOLEAN bNewTsdu = FALSE;
2857 tconn = (ksock_tconn_t *) ConnectionContext;
2859 bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
2861 KsPrint((2, "KsTcpChainedReceive: ReceiveLength = %xh bIsExpedited = %d\n", ReceiveLength, bIsExpedited));
2863 ks_get_tconn(tconn);
2864 spin_lock(&(tconn->kstc_lock));
2866 /* check whether we are conntected or not listener ¡Â*/
2867 if ( !((tconn->kstc_state == ksts_connected) &&
2868 (tconn->kstc_type == kstt_sender ||
2869 tconn->kstc_type == kstt_child))) {
2871 spin_unlock(&(tconn->kstc_lock));
2872 ks_put_tconn(tconn);
2874 return (STATUS_SUCCESS);
2877 /* get the latest Tsdu buffer form TsduMgr list.
2878 just set NULL if the list is empty. */
2880 if (tconn->kstc_type == kstt_sender) {
2881 KsChain = &(tconn->sender.kstc_recv);
2883 LASSERT(tconn->kstc_type == kstt_child);
2884 KsChain = &(tconn->child.kstc_recv);
2888 KsTsduMgr = &(KsChain->Expedited);
2890 KsTsduMgr = &(KsChain->Normal);
2893 if (list_empty(&(KsTsduMgr->TsduList))) {
2895 LASSERT(KsTsduMgr->NumOfTsdu == 0);
2900 LASSERT(KsTsduMgr->NumOfTsdu > 0);
2901 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
2902 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
2904 if (sizeof(KS_TSDU_MDL) > KsTsdu->TotalLength - KsTsdu->LastOffset) {
2909 /* if there's no Tsdu or the free size is not enough for this
2910 KS_TSDU_MDL structure. We need re-allocate a new Tsdu. */
2912 if (NULL == KsTsdu) {
2914 KsTsdu = KsAllocateKsTsdu();
2916 if (NULL == KsTsdu) {
2923 /* just queue the KS_TSDU_MDL to the Tsdu buffer */
2925 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
2927 KsTsduMdl->TsduType = TSDU_TYPE_MDL;
2928 KsTsduMdl->DataLength = ReceiveLength;
2929 KsTsduMdl->StartOffset = StartingOffset;
2930 KsTsduMdl->Mdl = Tsdu;
2931 KsTsduMdl->Descriptor = TsduDescriptor;
2933 KsTsdu->LastOffset += sizeof(KS_TSDU_MDL);
2934 KsTsduMgr->TotalBytes += ReceiveLength;
2936 KsPrint((2, "KsTcpChainedReceiveEventHandler: Total %xh bytes.\n",
2937 KsTsduMgr->TotalBytes ));
2939 Status = STATUS_PENDING;
2941 /* attach it to the TsduMgr list if the Tsdu is newly created. */
2944 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
2945 KsTsduMgr->NumOfTsdu++;
2948 spin_unlock(&(tconn->kstc_lock));
2950 /* wake up the threads waiing in ks_recv_mdl */
2951 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
2953 if (tconn->kstc_conn && tconn->kstc_sched_cb) {
2954 tconn->kstc_sched_cb( tconn, FALSE, NULL,
2955 KsTsduMgr->TotalBytes );
2958 ks_put_tconn(tconn);
2960 /* Return STATUS_PENDING to system because we are still
2961 owning the MDL resources. ks_recv_mdl is expected
2962 to free the MDL resources. */
2968 spin_unlock(&(tconn->kstc_lock));
2970 if (bNewTsdu && (KsTsdu != NULL)) {
2971 KsFreeKsTsdu(KsTsdu);
2974 /* abort the tdi connection */
2975 ks_abort_tconn(tconn);
2976 ks_put_tconn(tconn);
2979 Status = STATUS_SUCCESS;
2986 * Expedited & Bulk receive event handler
2990 KsTcpChainedReceiveExpeditedEventHandler (
2991 IN PVOID TdiEventContext, // the event context
2992 IN CONNECTION_CONTEXT ConnectionContext,
2993 IN ULONG ReceiveFlags,
2994 IN ULONG ReceiveLength,
2995 IN ULONG StartingOffset, // offset of start of client data in TSDU
2996 IN PMDL Tsdu, // TSDU data chain
2997 IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives
3000 return KsTcpChainedReceiveEventHandler(
3003 ReceiveFlags | TDI_RECEIVE_EXPEDITED,
3012 KsPrintProviderInfo(
3014 PTDI_PROVIDER_INFO ProviderInfo
3017 KsPrint((2, "%ws ProviderInfo:\n", DeviceName));
3019 KsPrint((2, " Version : 0x%4.4X\n", ProviderInfo->Version ));
3020 KsPrint((2, " MaxSendSize : %d\n", ProviderInfo->MaxSendSize ));
3021 KsPrint((2, " MaxConnectionUserData: %d\n", ProviderInfo->MaxConnectionUserData ));
3022 KsPrint((2, " MaxDatagramSize : %d\n", ProviderInfo->MaxDatagramSize ));
3023 KsPrint((2, " ServiceFlags : 0x%8.8X\n", ProviderInfo->ServiceFlags ));
3025 if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTION_MODE) {
3026 KsPrint((2, " CONNECTION_MODE\n"));
3029 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ORDERLY_RELEASE) {
3030 KsPrint((2, " ORDERLY_RELEASE\n"));
3033 if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTIONLESS_MODE) {
3034 KsPrint((2, " CONNECTIONLESS_MODE\n"));
3037 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ERROR_FREE_DELIVERY) {
3038 KsPrint((2, " ERROR_FREE_DELIVERY\n"));
3041 if( ProviderInfo->ServiceFlags & TDI_SERVICE_SECURITY_LEVEL ) {
3042 KsPrint((2, " SECURITY_LEVEL\n"));
3045 if (ProviderInfo->ServiceFlags & TDI_SERVICE_BROADCAST_SUPPORTED) {
3046 KsPrint((2, " BROADCAST_SUPPORTED\n"));
3049 if (ProviderInfo->ServiceFlags & TDI_SERVICE_MULTICAST_SUPPORTED) {
3050 KsPrint((2, " MULTICAST_SUPPORTED\n"));
3053 if (ProviderInfo->ServiceFlags & TDI_SERVICE_DELAYED_ACCEPTANCE) {
3054 KsPrint((2, " DELAYED_ACCEPTANCE\n"));
3057 if (ProviderInfo->ServiceFlags & TDI_SERVICE_EXPEDITED_DATA) {
3058 KsPrint((2, " EXPEDITED_DATA\n"));
3061 if( ProviderInfo->ServiceFlags & TDI_SERVICE_INTERNAL_BUFFERING) {
3062 KsPrint((2, " INTERNAL_BUFFERING\n"));
3065 if (ProviderInfo->ServiceFlags & TDI_SERVICE_ROUTE_DIRECTED) {
3066 KsPrint((2, " ROUTE_DIRECTED\n"));
3069 if (ProviderInfo->ServiceFlags & TDI_SERVICE_NO_ZERO_LENGTH) {
3070 KsPrint((2, " NO_ZERO_LENGTH\n"));
3073 if (ProviderInfo->ServiceFlags & TDI_SERVICE_POINT_TO_POINT) {
3074 KsPrint((2, " POINT_TO_POINT\n"));
3077 if (ProviderInfo->ServiceFlags & TDI_SERVICE_MESSAGE_MODE) {
3078 KsPrint((2, " MESSAGE_MODE\n"));
3081 if (ProviderInfo->ServiceFlags & TDI_SERVICE_HALF_DUPLEX) {
3082 KsPrint((2, " HALF_DUPLEX\n"));
3085 KsPrint((2, " MinimumLookaheadData : %d\n", ProviderInfo->MinimumLookaheadData ));
3086 KsPrint((2, " MaximumLookaheadData : %d\n", ProviderInfo->MaximumLookaheadData ));
3087 KsPrint((2, " NumberOfResources : %d\n", ProviderInfo->NumberOfResources ));
3093 * Reuse a Tsdu from the freelist or allocate a new Tsdu
3094 * from the LookAsideList table or the NonPagedPool
3100 * PKS_Tsdu: the new Tsdu or NULL if it fails
3109 PKS_TSDU KsTsdu = NULL;
3111 spin_lock(&(ks_data.ksnd_tsdu_lock));
3113 if (!list_empty (&(ks_data.ksnd_freetsdus))) {
3115 LASSERT(ks_data.ksnd_nfreetsdus > 0);
3117 KsTsdu = list_entry(ks_data.ksnd_freetsdus.next, KS_TSDU, Link);
3118 list_del(&(KsTsdu->Link));
3119 ks_data.ksnd_nfreetsdus--;
3123 KsTsdu = (PKS_TSDU) cfs_mem_cache_alloc(
3124 ks_data.ksnd_tsdu_slab, 0);
3127 spin_unlock(&(ks_data.ksnd_tsdu_lock));
3129 if (NULL != KsTsdu) {
3130 KsInitializeKsTsdu(KsTsdu, ks_data.ksnd_tsdu_size);
3139 * Move the Tsdu to the free tsdu list in ks_data.
3142 * KsTsdu: Tsdu to be moved.
3156 spin_lock(&(ks_data.ksnd_tsdu_lock));
3158 list_add_tail( &(KsTsdu->Link), &(ks_data.ksnd_freetsdus));
3159 ks_data.ksnd_nfreetsdus++;
3161 spin_unlock(&(ks_data.ksnd_tsdu_lock));
3167 * Release a Tsdu: uninitialize then free it.
3170 * KsTsdu: Tsdu to be freed.
3185 ks_data.ksnd_tsdu_slab,
3191 * KsInitializeKsTsdu
3192 * Initialize the Tsdu buffer header
3195 * KsTsdu: the Tsdu to be initialized
3196 * Length: the total length of the Tsdu
3211 RtlZeroMemory(KsTsdu, Length);
3212 KsTsdu->Magic = KS_TSDU_MAGIC;
3213 KsTsdu->TotalLength = Length;
3214 KsTsdu->StartOffset = KsTsdu->LastOffset =
3215 KS_DWORD_ALIGN(sizeof(KS_TSDU));
3220 * KsInitializeKsTsduMgr
3221 * Initialize the management structure of
3225 * TsduMgr: the TsduMgr to be initialized
3235 KsInitializeKsTsduMgr(
3246 &(TsduMgr->TsduList)
3249 TsduMgr->NumOfTsdu = 0;
3250 TsduMgr->TotalBytes = 0;
3255 * KsInitializeKsChain
3256 * Initialize the China structure for receiving
3260 * KsChain: the KsChain to be initialized
3270 KsInitializeKsChain(
3274 KsInitializeKsTsduMgr(&(KsChain->Normal));
3275 KsInitializeKsTsduMgr(&(KsChain->Expedited));
3281 * Clean up all the Tsdus in the TsduMgr list
3284 * KsTsduMgr: the Tsdu list manager
3287 * NTSTATUS: nt status code
3295 PKS_TSDUMGR KsTsduMgr
3299 PKS_TSDU_DAT KsTsduDat;
3300 PKS_TSDU_BUF KsTsduBuf;
3301 PKS_TSDU_MDL KsTsduMdl;
3303 LASSERT(NULL != KsTsduMgr);
3305 KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
3307 while (!list_empty(&KsTsduMgr->TsduList)) {
3309 KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
3310 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
3312 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
3315 // KsTsdu is empty now, we need free it ...
3318 list_del(&(KsTsdu->Link));
3319 KsTsduMgr->NumOfTsdu--;
3321 KsFreeKsTsdu(KsTsdu);
3325 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3326 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3327 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
3329 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
3331 KsTsdu->StartOffset += KsTsduDat->TotalLength;
3333 } else if (TSDU_TYPE_BUF == KsTsduBuf->TsduType) {
3335 ASSERT(KsTsduBuf->UserBuffer != NULL);
3337 if (KsTsduBuf->DataLength > KsTsduBuf->StartOffset) {
3338 ExFreePool(KsTsduBuf->UserBuffer);
3340 cfs_enter_debugger();
3343 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
3345 } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
3348 // MDL Tsdu Unit ...
3351 TdiReturnChainedReceives(
3352 &(KsTsduMdl->Descriptor),
3355 KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
3360 return STATUS_SUCCESS;
3366 * Clean up the TsduMgrs of the KsChain
3369 * KsChain: the chain managing TsduMgr
3372 * NTSTATUS: nt status code
3385 LASSERT(NULL != KsChain);
3387 Status = KsCleanupTsduMgr(
3391 if (!NT_SUCCESS(Status)) {
3392 cfs_enter_debugger();
3396 Status = KsCleanupTsduMgr(
3397 &(KsChain->Expedited)
3400 if (!NT_SUCCESS(Status)) {
3401 cfs_enter_debugger();
3413 * Clean up all the Tsdus of a tdi connected object
3416 * tconn: the tdi connection which is connected already.
3427 ksock_tconn_t * tconn
3430 NTSTATUS Status = STATUS_SUCCESS;
3433 if (tconn->kstc_type != kstt_sender &&
3434 tconn->kstc_type != kstt_child ) {
3439 if (tconn->kstc_type == kstt_sender) {
3441 Status = KsCleanupKsChain(
3442 &(tconn->sender.kstc_recv)
3445 if (!NT_SUCCESS(Status)) {
3446 cfs_enter_debugger();
3450 Status = KsCleanupKsChain(
3451 &(tconn->sender.kstc_send)
3454 if (!NT_SUCCESS(Status)) {
3455 cfs_enter_debugger();
3461 Status = KsCleanupKsChain(
3462 &(tconn->child.kstc_recv)
3465 if (!NT_SUCCESS(Status)) {
3466 cfs_enter_debugger();
3470 Status = KsCleanupKsChain(
3471 &(tconn->child.kstc_send)
3474 if (!NT_SUCCESS(Status)) {
3475 cfs_enter_debugger();
3488 * KsCopyMdlChainToMdlChain
3489 * Copy data from a [chained] Mdl to anther [chained] Mdl.
3490 * Tdi library does not provide this function. We have to
3491 * realize it ourselives.
3494 * SourceMdlChain: the source mdl
3495 * SourceOffset: start offset of the source
3496 * DestinationMdlChain: the dst mdl
3497 * DestinationOffset: the offset where data are to be copied.
3498 * BytesTobecopied: the expteced bytes to be copied
3499 * BytesCopied: to store the really copied data length
3502 * NTSTATUS: STATUS_SUCCESS or other error code
3505 * The length of source mdl must be >= SourceOffset + BytesTobecopied
3509 KsCopyMdlChainToMdlChain(
3510 IN PMDL SourceMdlChain,
3511 IN ULONG SourceOffset,
3512 IN PMDL DestinationMdlChain,
3513 IN ULONG DestinationOffset,
3514 IN ULONG BytesTobecopied,
3515 OUT PULONG BytesCopied
3518 PMDL SrcMdl = SourceMdlChain;
3519 PMDL DstMdl = DestinationMdlChain;
3521 PUCHAR SrcBuf = NULL;
3522 PUCHAR DstBuf = NULL;
3526 NTSTATUS Status = STATUS_SUCCESS;
3529 while (dwBytes < BytesTobecopied) {
3533 while (MmGetMdlByteCount(SrcMdl) <= SourceOffset) {
3535 SourceOffset -= MmGetMdlByteCount(SrcMdl);
3537 SrcMdl = SrcMdl->Next;
3539 if (NULL == SrcMdl) {
3541 Status = STATUS_INVALID_PARAMETER;
3546 while (MmGetMdlByteCount(DstMdl) <= DestinationOffset) {
3548 DestinationOffset -= MmGetMdlByteCount(DstMdl);
3550 DstMdl = DstMdl->Next;
3552 if (NULL == DstMdl) {
3554 Status = STATUS_INVALID_PARAMETER;
3559 DstBuf = (PUCHAR)KsMapMdlBuffer(DstMdl);
3561 if ((NULL == DstBuf)) {
3562 Status = STATUS_INSUFFICIENT_RESOURCES;
3567 // Here we need skip the OVERFLOW case via RtlCopyMemory :-(
3570 if ( KsQueryMdlsSize(SrcMdl) - SourceOffset >
3571 MmGetMdlByteCount(DstMdl) - DestinationOffset ) {
3573 Length = BytesTobecopied - dwBytes;
3575 if (Length > KsQueryMdlsSize(SrcMdl) - SourceOffset) {
3576 Length = KsQueryMdlsSize(SrcMdl) - SourceOffset;
3579 if (Length > MmGetMdlByteCount(DstMdl) - DestinationOffset) {
3580 Length = MmGetMdlByteCount(DstMdl) - DestinationOffset;
3583 SrcBuf = (PUCHAR)KsMapMdlBuffer(SrcMdl);
3585 if ((NULL == DstBuf)) {
3586 Status = STATUS_INSUFFICIENT_RESOURCES;
3591 DstBuf + DestinationOffset,
3592 SrcBuf + SourceOffset,
3598 Status = TdiCopyMdlToBuffer(
3603 MmGetMdlByteCount(DstMdl),
3607 if (STATUS_BUFFER_OVERFLOW == Status) {
3608 cfs_enter_debugger();
3609 } else if (!NT_SUCCESS(Status)) {
3610 cfs_enter_debugger();
3615 SourceOffset += Length;
3616 DestinationOffset += Length;
3622 if (NT_SUCCESS(Status)) {
3623 *BytesCopied = dwBytes;
3635 * Query the whole size of a MDL (may be chained)
3638 * Mdl: the Mdl to be queried
3641 * ULONG: the total size of the mdl
3648 KsQueryMdlsSize (PMDL Mdl)
3655 // Walking the MDL Chain ...
3659 Length += MmGetMdlByteCount(Next);
3669 * Allocate MDL for the buffer and lock the pages into
3673 * UserBuffer: the user buffer to be locked
3674 * Length: length in bytes of the buffer
3675 * Operation: read or write access
3676 * pMdl: the result of the created mdl
3679 * NTSTATUS: kernel status code (STATUS_SUCCESS
3680 * or other error code)
3688 IN PVOID UserBuffer,
3691 IN LOCK_OPERATION Operation,
3698 LASSERT(UserBuffer != NULL);
3702 Mdl = IoAllocateMdl(
3712 Status = STATUS_INSUFFICIENT_RESOURCES;
3719 MmProbeAndLockPages(
3725 MmBuildMdlForNonPagedPool(
3730 Status = STATUS_SUCCESS;
3734 } __except (EXCEPTION_EXECUTE_HANDLER) {
3740 cfs_enter_debugger();
3742 Status = STATUS_INVALID_USER_BUFFER;
3751 * Map the mdl into a buffer in kernel space
3754 * Mdl: the mdl to be mapped
3757 * PVOID: the buffer mapped or NULL in failure
3764 KsMapMdlBuffer (PMDL Mdl)
3766 LASSERT(Mdl != NULL);
3768 return MmGetSystemAddressForMdlSafe(
3777 * Unlock all the pages in the mdl
3780 * Mdl: memory description list to be released
3790 KsReleaseMdl (IN PMDL Mdl,
3793 LASSERT(Mdl != NULL);
3814 * allocate MDL for the user spepcified buffer and lock (paging-in)
3815 * all the pages of the buffer into system memory
3818 * buffer: the user buffer to be locked
3819 * length: length in bytes of the buffer
3820 * access: read or write access
3821 * mdl: the result of the created mdl
3824 * int: the ks error code: 0: success / -x: failture
3835 LOCK_OPERATION access,
3841 status = KsLockUserBuffer(
3849 return cfs_error_code(status);
3855 * Map the mdl pages into kernel space
3858 * mdl: the mdl to be mapped
3861 * void *: the buffer mapped or NULL in failure
3868 ks_map_mdl (ksock_mdl_t * mdl)
3870 LASSERT(mdl != NULL);
3872 return KsMapMdlBuffer(mdl);
3877 * Unlock all the pages in the mdl and release the mdl
3880 * mdl: memory description list to be released
3890 ks_release_mdl (ksock_mdl_t *mdl, int paged)
3892 LASSERT(mdl != NULL);
3894 KsReleaseMdl(mdl, paged);
3900 * allocate a new tconn structure from the SLAB cache or
3901 * NonPaged sysetm pool
3907 * ksock_tconn_t *: the address of tconn or NULL if it fails
3916 ksock_tconn_t * tconn = NULL;
3918 /* allocate ksoc_tconn_t from the slab cache memory */
3920 tconn = (ksock_tconn_t *)cfs_mem_cache_alloc(
3921 ks_data.ksnd_tconn_slab, CFS_ALLOC_ZERO);
3925 /* zero tconn elements */
3926 memset(tconn, 0, sizeof(ksock_tconn_t));
3928 /* initialize the tconn ... */
3929 tconn->kstc_magic = KS_TCONN_MAGIC;
3931 ExInitializeWorkItem(
3932 &(tconn->kstc_disconnect.WorkItem),
3934 &(tconn->kstc_disconnect)
3938 &(tconn->kstc_disconnect.Event),
3939 SynchronizationEvent,
3942 ExInitializeWorkItem(
3943 &(tconn->kstc_destroy),
3948 spin_lock_init(&(tconn->kstc_lock));
3950 ks_get_tconn(tconn);
3952 spin_lock(&(ks_data.ksnd_tconn_lock));
3954 /* attach it into global list in ks_data */
3956 list_add(&(tconn->kstc_list), &(ks_data.ksnd_tconns));
3957 ks_data.ksnd_ntconns++;
3958 spin_unlock(&(ks_data.ksnd_tconn_lock));
3960 tconn->kstc_rcv_wnd = tconn->kstc_snd_wnd = 0x10000;
3969 * free the tconn structure to the SLAB cache or NonPaged
3973 * tconn: the tcon is to be freed
3983 ks_free_tconn(ksock_tconn_t * tconn)
3985 LASSERT(atomic_read(&(tconn->kstc_refcount)) == 0);
3987 spin_lock(&(ks_data.ksnd_tconn_lock));
3989 /* remove it from the global list */
3990 list_del(&tconn->kstc_list);
3991 ks_data.ksnd_ntconns--;
3993 /* if this is the last tconn, it would be safe for
3994 ks_tdi_fini_data to quit ... */
3995 if (ks_data.ksnd_ntconns == 0) {
3996 cfs_wake_event(&ks_data.ksnd_tconn_exit);
3998 spin_unlock(&(ks_data.ksnd_tconn_lock));
4000 /* free the structure memory */
4001 cfs_mem_cache_free(ks_data.ksnd_tconn_slab, tconn);
4007 * Initialize the tconn as a listener (daemon)
4010 * tconn: the listener tconn
4021 ksock_tconn_t * tconn
4024 /* preparation: intialize the tconn members */
4026 tconn->kstc_type = kstt_listener;
4028 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4030 CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_listening.list));
4031 CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_accepted.list));
4033 cfs_init_event( &(tconn->listener.kstc_accept_event),
4037 cfs_init_event( &(tconn->listener.kstc_destroy_event),
4041 tconn->kstc_state = ksts_inited;
4047 * Initialize the tconn as a sender
4050 * tconn: the sender tconn
4061 ksock_tconn_t * tconn
4064 tconn->kstc_type = kstt_sender;
4065 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4067 KsInitializeKsChain(&(tconn->sender.kstc_recv));
4068 KsInitializeKsChain(&(tconn->sender.kstc_send));
4070 tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4071 tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4073 tconn->kstc_state = ksts_inited;
4078 * Initialize the tconn as a child
4081 * tconn: the child tconn
4092 ksock_tconn_t * tconn
4095 tconn->kstc_type = kstt_child;
4096 RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
4098 KsInitializeKsChain(&(tconn->child.kstc_recv));
4099 KsInitializeKsChain(&(tconn->child.kstc_send));
4101 tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4102 tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
4104 tconn->kstc_state = ksts_inited;
4109 * increase the reference count of the tconn with 1
4112 * tconn: the tdi connection to be referred
4123 ksock_tconn_t * tconn
4126 atomic_inc(&(tconn->kstc_refcount));
4131 * decrease the reference count of the tconn and destroy
4132 * it if the refercount becomes 0.
4135 * tconn: the tdi connection to be dereferred
4146 ksock_tconn_t *tconn
4149 if (atomic_dec_and_test(&(tconn->kstc_refcount))) {
4151 spin_lock(&(tconn->kstc_lock));
4153 if ( ( tconn->kstc_type == kstt_child ||
4154 tconn->kstc_type == kstt_sender ) &&
4155 ( tconn->kstc_state == ksts_connected ) ) {
4157 spin_unlock(&(tconn->kstc_lock));
4159 ks_abort_tconn(tconn);
4163 if (cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY)) {
4164 cfs_enter_debugger();
4167 &(tconn->kstc_destroy),
4171 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY);
4174 spin_unlock(&(tconn->kstc_lock));
4181 * cleanup the tdi connection and free it
4184 * tconn: the tdi connection to be cleaned.
4195 ksock_tconn_t * tconn
4198 LASSERT(tconn->kstc_refcount.counter == 0);
4200 if (tconn->kstc_type == kstt_listener) {
4202 ks_reset_handlers(tconn);
4204 /* for listener, we just need to close the address object */
4206 tconn->kstc_addr.Handle,
4207 tconn->kstc_addr.FileObject
4210 tconn->kstc_state = ksts_inited;
4212 } else if (tconn->kstc_type == kstt_child) {
4214 /* for child tdi conections */
4216 /* disassociate the relation between it's connection object
4217 and the address object */
4219 if (tconn->kstc_state == ksts_associated) {
4220 KsDisassociateAddress(
4221 tconn->child.kstc_info.FileObject
4225 /* release the connection object */
4228 tconn->child.kstc_info.Handle,
4229 tconn->child.kstc_info.FileObject
4232 /* release it's refer of it's parent's address object */
4235 tconn->kstc_addr.FileObject
4238 spin_lock(&tconn->child.kstc_parent->kstc_lock);
4239 spin_lock(&tconn->kstc_lock);
4241 tconn->kstc_state = ksts_inited;
4243 /* remove it frome it's parent's queues */
4245 if (tconn->child.kstc_queued) {
4247 list_del(&(tconn->child.kstc_link));
4249 if (tconn->child.kstc_queueno) {
4251 LASSERT(tconn->child.kstc_parent->listener.kstc_accepted.num > 0);
4252 tconn->child.kstc_parent->listener.kstc_accepted.num -= 1;
4256 LASSERT(tconn->child.kstc_parent->listener.kstc_listening.num > 0);
4257 tconn->child.kstc_parent->listener.kstc_listening.num -= 1;
4260 tconn->child.kstc_queued = FALSE;
4263 spin_unlock(&tconn->kstc_lock);
4264 spin_unlock(&tconn->child.kstc_parent->kstc_lock);
4266 /* drop the reference of the parent tconn */
4267 ks_put_tconn(tconn->child.kstc_parent);
4269 } else if (tconn->kstc_type == kstt_sender) {
4271 ks_reset_handlers(tconn);
4273 /* release the connection object */
4276 tconn->sender.kstc_info.Handle,
4277 tconn->sender.kstc_info.FileObject
4280 /* release it's refer of it's parent's address object */
4282 tconn->kstc_addr.Handle,
4283 tconn->kstc_addr.FileObject
4286 tconn->kstc_state = ksts_inited;
4289 cfs_enter_debugger();
4292 /* free the tconn structure ... */
4294 ks_free_tconn(tconn);
4299 ksock_tconn_t * tconn,
4306 PKS_TSDUMGR KsTsduMgr;
4310 ks_get_tconn(tconn);
4311 spin_lock(&(tconn->kstc_lock));
4313 if ( tconn->kstc_type != kstt_sender &&
4314 tconn->kstc_type != kstt_child) {
4316 spin_unlock(&(tconn->kstc_lock));
4320 if (tconn->kstc_state != ksts_connected) {
4322 spin_unlock(&(tconn->kstc_lock));
4326 if (tconn->kstc_type == kstt_sender) {
4327 KsChain = &(tconn->sender.kstc_recv);
4329 LASSERT(tconn->kstc_type == kstt_child);
4330 KsChain = &(tconn->child.kstc_recv);
4334 KsTsduMgr = &(KsChain->Expedited);
4336 KsTsduMgr = &(KsChain->Normal);
4339 *size = KsTsduMgr->TotalBytes;
4340 spin_unlock(&(tconn->kstc_lock));
4344 ks_put_tconn(tconn);
4351 * Query the the options of the tcp stream connnection
4354 * tconn: the tdi connection
4356 * OptionValue: buffer to store the option value
4357 * Length: the length of the value, to be returned
4360 * int: ks return code
4368 ksock_tconn_t * tconn,
4374 NTSTATUS Status = STATUS_SUCCESS;
4376 IO_STATUS_BLOCK IoStatus;
4378 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfoEx;
4380 PFILE_OBJECT ConnectionObject;
4381 PDEVICE_OBJECT DeviceObject = NULL;
4384 PIO_STACK_LOCATION IrpSp = NULL;
4388 /* make sure the tdi connection is connected ? */
4390 ks_get_tconn(tconn);
4392 if (tconn->kstc_state != ksts_connected) {
4393 Status = STATUS_INVALID_PARAMETER;
4397 LASSERT(tconn->kstc_type == kstt_sender ||
4398 tconn->kstc_type == kstt_child);
4400 if (tconn->kstc_type == kstt_sender) {
4401 ConnectionObject = tconn->sender.kstc_info.FileObject;
4403 ConnectionObject = tconn->child.kstc_info.FileObject;
4406 QueryInfoEx.ID.toi_id = ID;
4407 QueryInfoEx.ID.toi_type = INFO_TYPE_CONNECTION;
4408 QueryInfoEx.ID.toi_class = INFO_CLASS_PROTOCOL;
4409 QueryInfoEx.ID.toi_entity.tei_entity = CO_TL_ENTITY;
4410 QueryInfoEx.ID.toi_entity.tei_instance = 0;
4412 RtlZeroMemory(&(QueryInfoEx.Context), CONTEXT_SIZE);
4414 KeInitializeEvent(&Event, NotificationEvent, FALSE);
4415 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4417 Irp = IoBuildDeviceIoControlRequest(
4418 IOCTL_TCP_QUERY_INFORMATION_EX,
4421 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
4430 Status = STATUS_INSUFFICIENT_RESOURCES;
4434 IrpSp = IoGetNextIrpStackLocation(Irp);
4436 if (IrpSp == NULL) {
4440 Status = STATUS_INSUFFICIENT_RESOURCES;
4444 IrpSp->FileObject = ConnectionObject;
4445 IrpSp->DeviceObject = DeviceObject;
4447 Status = IoCallDriver(DeviceObject, Irp);
4449 if (Status == STATUS_PENDING) {
4451 KeWaitForSingleObject(
4459 Status = IoStatus.Status;
4463 if (NT_SUCCESS(Status)) {
4464 *Length = IoStatus.Information;
4466 cfs_enter_debugger();
4467 memset(OptionValue, 0, *Length);
4468 Status = STATUS_SUCCESS;
4473 ks_put_tconn(tconn);
4475 return cfs_error_code(Status);
4480 * Set the the options for the tcp stream connnection
4483 * tconn: the tdi connection
4485 * OptionValue: buffer containing the new option value
4486 * Length: the length of the value
4489 * int: ks return code
4497 ksock_tconn_t * tconn,
4503 NTSTATUS Status = STATUS_SUCCESS;
4505 IO_STATUS_BLOCK IoStatus;
4507 ULONG SetInfoExLength;
4508 PTCP_REQUEST_SET_INFORMATION_EX SetInfoEx = NULL;
4510 PFILE_OBJECT ConnectionObject;
4511 PDEVICE_OBJECT DeviceObject = NULL;
4514 PIO_STACK_LOCATION IrpSp = NULL;
4518 /* make sure the tdi connection is connected ? */
4520 ks_get_tconn(tconn);
4522 if (tconn->kstc_state != ksts_connected) {
4523 Status = STATUS_INVALID_PARAMETER;
4527 LASSERT(tconn->kstc_type == kstt_sender ||
4528 tconn->kstc_type == kstt_child);
4530 if (tconn->kstc_type == kstt_sender) {
4531 ConnectionObject = tconn->sender.kstc_info.FileObject;
4533 ConnectionObject = tconn->child.kstc_info.FileObject;
4536 SetInfoExLength = sizeof(TCP_REQUEST_SET_INFORMATION_EX) - 1 + Length + sizeof(KEVENT);
4538 SetInfoEx = ExAllocatePoolWithTag(
4544 if (SetInfoEx == NULL) {
4545 Status = STATUS_INSUFFICIENT_RESOURCES;
4549 SetInfoEx->ID.toi_id = ID;
4551 SetInfoEx->ID.toi_type = INFO_TYPE_CONNECTION;
4552 SetInfoEx->ID.toi_class = INFO_CLASS_PROTOCOL;
4553 SetInfoEx->ID.toi_entity.tei_entity = CO_TL_ENTITY;
4554 SetInfoEx->ID.toi_entity.tei_instance = TL_INSTANCE;
4556 SetInfoEx->BufferSize = Length;
4557 RtlCopyMemory(&(SetInfoEx->Buffer[0]), OptionValue, Length);
4559 Event = (PKEVENT)(&(SetInfoEx->Buffer[Length]));
4560 KeInitializeEvent(Event, NotificationEvent, FALSE);
4562 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4564 Irp = IoBuildDeviceIoControlRequest(
4565 IOCTL_TCP_SET_INFORMATION_EX,
4577 Status = STATUS_INSUFFICIENT_RESOURCES;
4581 IrpSp = IoGetNextIrpStackLocation(Irp);
4583 if (IrpSp == NULL) {
4586 Status = STATUS_INSUFFICIENT_RESOURCES;
4590 IrpSp->FileObject = ConnectionObject;
4591 IrpSp->DeviceObject = DeviceObject;
4593 Status = IoCallDriver(DeviceObject, Irp);
4595 if (Status == STATUS_PENDING) {
4597 KeWaitForSingleObject(
4605 Status = IoStatus.Status;
4611 ExFreePool(SetInfoEx);
4614 if (!NT_SUCCESS(Status)) {
4615 printk("ks_set_tcp_option: error setup tcp option: ID (%d), Status = %xh\n",
4617 Status = STATUS_SUCCESS;
4620 ks_put_tconn(tconn);
4622 return cfs_error_code(Status);
4627 * bind the tdi connection object with an address
4630 * tconn: tconn to be bound
4631 * parent: the parent tconn object
4632 * ipaddr: the ip address
4633 * port: the port number
4636 * int: 0 for success or ks error codes.
4644 ksock_tconn_t * tconn,
4645 ksock_tconn_t * parent,
4653 ksock_tdi_addr_t taddr;
4655 memset(&taddr, 0, sizeof(ksock_tdi_addr_t));
4657 if (tconn->kstc_state != ksts_inited) {
4659 status = STATUS_INVALID_PARAMETER;
4660 rc = cfs_error_code(status);
4664 } else if (tconn->kstc_type == kstt_child) {
4666 if (NULL == parent) {
4667 status = STATUS_INVALID_PARAMETER;
4668 rc = cfs_error_code(status);
4673 /* refer it's parent's address object */
4675 taddr = parent->kstc_addr;
4676 ObReferenceObject(taddr.FileObject);
4678 ks_get_tconn(parent);
4682 PTRANSPORT_ADDRESS TdiAddress = &(taddr.Tdi);
4685 /* intialize the tdi address*/
4687 TdiAddress->TAAddressCount = 1;
4688 TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
4689 TdiAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
4691 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
4692 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
4694 memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
4697 /* open the transport address object */
4699 AddrLen = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) +
4700 TDI_ADDRESS_LENGTH_IP;
4702 status = KsOpenAddress(
4710 if (!NT_SUCCESS(status)) {
4712 KsPrint((0, "ks_bind_tconn: failed to open ip addr object (%x:%d), status = %xh\n",
4713 addr, port, status ));
4714 rc = cfs_error_code(status);
4719 if (tconn->kstc_type == kstt_child) {
4720 tconn->child.kstc_parent = parent;
4723 tconn->kstc_state = ksts_bind;
4724 tconn->kstc_addr = taddr;
4733 * build tcp/streaming connection to remote peer
4736 * tconn: tconn to be connected to the peer
4737 * addr: the peer's ip address
4738 * port: the peer's port number
4741 * int: 0 for success or ks error codes.
4749 ksock_tconn_t * tconn,
4755 NTSTATUS status = STATUS_SUCCESS;
4758 PFILE_OBJECT ConnectionObject = NULL;
4759 PDEVICE_OBJECT DeviceObject = NULL;
4761 PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
4766 LASSERT(tconn->kstc_type == kstt_sender);
4767 LASSERT(tconn->kstc_state == ksts_bind);
4769 ks_get_tconn(tconn);
4772 /* set the event callbacks */
4773 rc = ks_set_handlers(tconn);
4776 cfs_enter_debugger();
4781 /* create the connection file handle / object */
4782 status = KsOpenConnection(
4784 (CONNECTION_CONTEXT)tconn,
4785 &(tconn->sender.kstc_info.Handle),
4786 &(tconn->sender.kstc_info.FileObject)
4789 if (!NT_SUCCESS(status)) {
4790 rc = cfs_error_code(status);
4791 cfs_enter_debugger();
4795 /* associdate the the connection with the adress object of the tconn */
4797 status = KsAssociateAddress(
4798 tconn->kstc_addr.Handle,
4799 tconn->sender.kstc_info.FileObject
4802 if (!NT_SUCCESS(status)) {
4803 rc = cfs_error_code(status);
4804 cfs_enter_debugger();
4808 tconn->kstc_state = ksts_associated;
4810 /* Allocating Connection Info Together with the Address */
4811 AddrLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
4812 + TDI_ADDRESS_LENGTH_IP;
4814 ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
4815 NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + AddrLength, 'iCsK');
4817 if (NULL == ConnectionInfo) {
4819 status = STATUS_INSUFFICIENT_RESOURCES;
4820 rc = cfs_error_code(status);
4821 cfs_enter_debugger();
4825 /* Initializing ConnectionInfo ... */
4827 PTRANSPORT_ADDRESS TdiAddress;
4829 /* ConnectionInfo settings */
4831 ConnectionInfo->UserDataLength = 0;
4832 ConnectionInfo->UserData = NULL;
4833 ConnectionInfo->OptionsLength = 0;
4834 ConnectionInfo->Options = NULL;
4835 ConnectionInfo->RemoteAddressLength = AddrLength;
4836 ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
4839 /* intialize the tdi address*/
4841 TdiAddress = ConnectionInfo->RemoteAddress;
4843 TdiAddress->TAAddressCount = 1;
4844 TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
4845 TdiAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
4847 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
4848 ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
4850 memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
4853 /* Now prepare to connect the remote peer ... */
4855 ConnectionObject = tconn->sender.kstc_info.FileObject;
4856 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
4858 /* allocate a new Irp */
4860 Irp = KsBuildTdiIrp(DeviceObject);
4864 status = STATUS_INSUFFICIENT_RESOURCES;
4865 rc = cfs_error_code(status);
4866 cfs_enter_debugger();
4884 /* sumbit the Irp to the underlying transport driver */
4885 status = KsSubmitTdiIrp(
4892 spin_lock(&(tconn->kstc_lock));
4894 if (NT_SUCCESS(status)) {
4896 /* Connected! the conneciton is built successfully. */
4898 tconn->kstc_state = ksts_connected;
4900 tconn->sender.kstc_info.ConnectionInfo = ConnectionInfo;
4901 tconn->sender.kstc_info.Remote = ConnectionInfo->RemoteAddress;
4903 spin_unlock(&(tconn->kstc_lock));
4907 /* Not connected! Abort it ... */
4910 cfs_enter_debugger();
4914 rc = cfs_error_code(status);
4916 tconn->kstc_state = ksts_associated;
4917 spin_unlock(&(tconn->kstc_lock));
4919 /* disassocidate the connection and the address object,
4920 after cleanup, it's safe to set the state to abort ... */
4922 if ( NT_SUCCESS(KsDisassociateAddress(
4923 tconn->sender.kstc_info.FileObject))) {
4924 tconn->kstc_state = ksts_aborted;
4927 /* reset the event callbacks */
4928 rc = ks_reset_handlers(tconn);
4935 if (NT_SUCCESS(status)) {
4937 ks_query_local_ipaddr(tconn);
4941 if (ConnectionInfo) {
4942 ExFreePool(ConnectionInfo);
4949 ks_put_tconn(tconn);
4956 * ks_disconnect_tconn
4957 * disconnect the tconn from a connection
4960 * tconn: the tdi connecton object connected already
4961 * flags: flags & options for disconnecting
4964 * int: ks error code
4971 ks_disconnect_tconn(
4972 ksock_tconn_t * tconn,
4976 NTSTATUS status = STATUS_SUCCESS;
4978 ksock_tconn_info_t * info;
4980 PFILE_OBJECT ConnectionObject;
4981 PDEVICE_OBJECT DeviceObject = NULL;
4987 ks_get_tconn(tconn);
4989 /* make sure tt's connected already and it
4990 must be a sender or a child ... */
4992 LASSERT(tconn->kstc_state == ksts_connected);
4993 LASSERT( tconn->kstc_type == kstt_sender ||
4994 tconn->kstc_type == kstt_child);
4996 /* reset all the event handlers to NULL */
4998 if (tconn->kstc_type != kstt_child) {
4999 ks_reset_handlers (tconn);
5002 /* Disconnecting to the remote peer ... */
5004 if (tconn->kstc_type == kstt_sender) {
5005 info = &(tconn->sender.kstc_info);
5007 info = &(tconn->child.kstc_info);
5010 ConnectionObject = info->FileObject;
5011 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
5013 /* allocate an Irp and setup it */
5015 Irp = KsBuildTdiIrp(DeviceObject);
5019 status = STATUS_INSUFFICIENT_RESOURCES;
5020 cfs_enter_debugger();
5026 SynchronizationEvent,
5034 KsDisconectCompletionRoutine,
5042 /* issue the Irp to the underlying transport
5043 driver to disconnect the connection */
5045 status = IoCallDriver(DeviceObject, Irp);
5047 if (STATUS_PENDING == status) {
5049 status = KeWaitForSingleObject(
5057 status = Irp->IoStatus.Status;
5060 KsPrint((2, "KsDisconnect: Disconnection is done with Status = %xh (%s) ...\n",
5061 status, KsNtStatusToString(status)));
5065 if (info->ConnectionInfo) {
5067 /* disassociate the association between connection/address objects */
5069 status = KsDisassociateAddress(ConnectionObject);
5071 if (!NT_SUCCESS(status)) {
5072 cfs_enter_debugger();
5075 spin_lock(&(tconn->kstc_lock));
5077 /* cleanup the tsdumgr Lists */
5078 KsCleanupTsdu (tconn);
5080 /* set the state of the tconn */
5081 if (NT_SUCCESS(status)) {
5082 tconn->kstc_state = ksts_disconnected;
5084 tconn->kstc_state = ksts_associated;
5087 /* free the connection info to system pool*/
5088 ExFreePool(info->ConnectionInfo);
5089 info->ConnectionInfo = NULL;
5090 info->Remote = NULL;
5092 spin_unlock(&(tconn->kstc_lock));
5095 status = STATUS_SUCCESS;
5099 ks_put_tconn(tconn);
5101 return cfs_error_code(status);
5107 * The connection is broken un-expectedly. We need do
5111 * tconn: the tdi connection
5122 ksock_tconn_t * tconn
5125 PKS_DISCONNECT_WORKITEM WorkItem = NULL;
5127 WorkItem = &(tconn->kstc_disconnect);
5129 ks_get_tconn(tconn);
5130 spin_lock(&(tconn->kstc_lock));
5132 if (tconn->kstc_state != ksts_connected) {
5133 ks_put_tconn(tconn);
5136 if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
5138 WorkItem->Flags = TDI_DISCONNECT_ABORT;
5139 WorkItem->tconn = tconn;
5141 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
5144 &(WorkItem->WorkItem),
5150 spin_unlock(&(tconn->kstc_lock));
5155 * ks_query_local_ipaddr
5156 * query the local connection ip address
5159 * tconn: the tconn which is connected
5162 * int: ks error code
5169 ks_query_local_ipaddr(
5170 ksock_tconn_t * tconn
5173 PFILE_OBJECT FileObject = NULL;
5176 PTRANSPORT_ADDRESS TdiAddress;
5177 ULONG AddressLength;
5179 if (tconn->kstc_type == kstt_sender) {
5180 FileObject = tconn->sender.kstc_info.FileObject;
5181 } else if (tconn->kstc_type == kstt_child) {
5182 FileObject = tconn->child.kstc_info.FileObject;
5184 status = STATUS_INVALID_PARAMETER;
5188 TdiAddress = &(tconn->kstc_addr.Tdi);
5189 AddressLength = MAX_ADDRESS_LENGTH;
5191 status = KsQueryIpAddress(FileObject, TdiAddress, &AddressLength);
5193 if (NT_SUCCESS(status)) {
5195 KsPrint((0, "ks_query_local_ipaddr: Local ip address = %xh port = %xh\n",
5196 ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->in_addr,
5197 ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->sin_port ));
5199 KsPrint((0, "KsQueryonnectionIpAddress: Failed to query the connection local ip address.\n"));
5204 return cfs_error_code(status);
5209 * send MDL chain to the peer for a stream connection
5212 * tconn: tdi connection object
5213 * tx: the transmit context
5214 * mdl: the mdl chain containing the data
5215 * len: length of the data
5216 * flags: flags of the transmission
5227 ksock_tconn_t * tconn,
5238 ksock_tdi_tx_t * context;
5241 PKS_TSDUMGR KsTsduMgr;
5243 PKS_TSDU_BUF KsTsduBuf;
5244 PKS_TSDU_DAT KsTsduDat;
5246 BOOLEAN bNewTsdu = FALSE; /* newly allocated */
5247 BOOLEAN bNewBuff = FALSE; /* newly allocated */
5249 BOOLEAN bBuffed; /* bufferred sending */
5251 PUCHAR Buffer = NULL;
5252 ksock_mdl_t * NewMdl = NULL;
5255 PFILE_OBJECT ConnObject;
5256 PDEVICE_OBJECT DeviceObject;
5258 BOOLEAN bIsNonBlock;
5260 ks_get_tconn(tconn);
5262 tflags = ks_tdi_send_flags(flags);
5263 bIsNonBlock = cfs_is_flag_set(flags, MSG_DONTWAIT);
5265 spin_lock(&tconn->kstc_lock);
5267 LASSERT( tconn->kstc_type == kstt_sender ||
5268 tconn->kstc_type == kstt_child );
5270 if (tconn->kstc_state != ksts_connected) {
5271 spin_unlock(&tconn->kstc_lock);
5272 ks_put_tconn(tconn);
5276 /* get the latest Tsdu buffer form TsduMgr list.
5277 just set NULL if the list is empty. */
5279 if (tconn->kstc_type == kstt_sender) {
5280 KsChain = &(tconn->sender.kstc_send);
5282 LASSERT(tconn->kstc_type == kstt_child);
5283 KsChain = &(tconn->child.kstc_send);
5286 if (cfs_is_flag_set(tflags, TDI_SEND_EXPEDITED)) {
5287 KsTsduMgr = &(KsChain->Expedited);
5289 KsTsduMgr = &(KsChain->Normal);
5292 if (KsTsduMgr->TotalBytes + len <= tconn->kstc_snd_wnd) {
5298 /* do the preparation work for bufferred sending */
5302 /* if the data is even larger than the biggest Tsdu, we have
5303 to allocate new buffer and use TSDU_TYOE_BUF to store it */
5305 if ( KS_TSDU_STRU_SIZE((ULONG)len) > ks_data.ksnd_tsdu_size
5306 - KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
5310 if (list_empty(&(KsTsduMgr->TsduList))) {
5312 LASSERT(KsTsduMgr->NumOfTsdu == 0);
5317 LASSERT(KsTsduMgr->NumOfTsdu > 0);
5318 KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
5319 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
5322 /* check whether KsTsdu free space is enough, or we need alloc new Tsdu */
5324 if (sizeof(KS_TSDU_BUF) + KsTsdu->LastOffset > KsTsdu->TotalLength) {
5328 if ( KS_TSDU_STRU_SIZE((ULONG)len) >
5329 KsTsdu->TotalLength - KsTsdu->LastOffset ) {
5335 /* if there's no Tsdu or the free size is not enough for the
5336 KS_TSDU_BUF or KS_TSDU_DAT. We need re-allocate a new Tsdu. */
5338 if (NULL == KsTsdu) {
5340 KsTsdu = KsAllocateKsTsdu();
5342 if (NULL == KsTsdu) {
5350 /* process the case that a new buffer is to be allocated from system memory */
5353 /* now allocating internal buffer to contain the payload */
5354 Buffer = ExAllocatePool(NonPagedPool, len);
5356 if (NULL == Buffer) {
5366 /* queue a new KS_TSDU_BUF to the Tsdu buffer */
5367 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
5369 KsTsduBuf->TsduFlags = 0;
5370 KsTsduBuf->DataLength = (ULONG)len;
5371 KsTsduBuf->StartOffset = 0;
5372 KsTsduBuf->UserBuffer = Buffer;
5374 /* queue a new KS_TSDU_BUF to the Tsdu buffer */
5375 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
5377 KsTsduDat->TsduFlags = 0;
5378 KsTsduDat->DataLength = (ULONG)len;
5379 KsTsduDat->StartOffset = 0;
5380 KsTsduDat->TotalLength = KS_TSDU_STRU_SIZE((ULONG)len);
5382 Buffer = &KsTsduDat->Data[0];
5385 /* now locking the Buffer and copy user payload into the buffer */
5386 ASSERT(Buffer != NULL);
5388 rc = ks_lock_buffer(Buffer, FALSE, len, IoReadAccess, &NewMdl);
5390 printk("ks_send_mdl: bufferred: error allocating mdl.\n");
5393 ULONG BytesCopied = 0;
5394 TdiCopyMdlToBuffer(mdl, 0, Buffer, 0, (ULONG)len, &BytesCopied);
5395 if (BytesCopied != (ULONG) len) {
5400 /* Do the finializing job if we succeed to to lock the buffer and move
5401 user data. Or we need do cleaning up ... */
5405 KsTsduBuf->TsduType = TSDU_TYPE_BUF;
5406 KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
5409 KsTsduDat->TsduType = TSDU_TYPE_DAT;
5410 KsTsdu->LastOffset += KsTsduDat->TotalLength;
5413 /* attach it to the TsduMgr list if the Tsdu is newly created. */
5416 list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
5417 KsTsduMgr->NumOfTsdu++;
5423 ks_release_mdl(NewMdl, FALSE);
5435 /* update the TotalBytes being in sending */
5436 KsTsduMgr->TotalBytes += (ULONG)len;
5438 spin_unlock(&tconn->kstc_lock);
5440 /* cleanup the Tsdu if not successful */
5441 if (!bBuffed && bNewTsdu) {
5442 KsPutKsTsdu(KsTsdu);
5447 /* we need allocate the ksock_tx_t structure from memory pool. */
5449 context = cfs_alloc(sizeof(ksock_tdi_tx_t) + sizeof(KEVENT),0);
5451 /* release the chained mdl */
5452 ks_release_mdl(mdl, FALSE);
5454 Status = STATUS_INSUFFICIENT_RESOURCES;
5458 /* intialize the TcpContext */
5460 memset(context,0, sizeof(ksock_tdi_tx_t) + sizeof(KEVENT));
5462 context->tconn = tconn;
5463 context->Event = (PKEVENT) ((PUCHAR)context + sizeof(ksock_tdi_tx_t));
5465 KeInitializeEvent(context->Event, SynchronizationEvent, FALSE);
5469 /* for bufferred transmission, we need set
5470 the internal completion routine. */
5472 context->CompletionRoutine = KsTcpSendCompletionRoutine;
5473 context->KsTsduMgr = KsTsduMgr;
5474 context->CompletionContext = KsTsdu;
5475 context->CompletionContext2 = (bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat);
5476 context->bCounted = FALSE;
5478 } else if (bIsNonBlock) {
5480 /* for non-blocking transmission, we need set
5481 the internal completion routine too. */
5483 context->CompletionRoutine = KsTcpSendCompletionRoutine;
5484 context->CompletionContext = tx;
5485 context->KsTsduMgr = KsTsduMgr;
5486 context->bCounted = TRUE;
5487 context->ReferCount = 2;
5490 if (tconn->kstc_type == kstt_sender) {
5491 ConnObject = tconn->sender.kstc_info.FileObject;
5493 LASSERT(tconn->kstc_type == kstt_child);
5494 ConnObject = tconn->child.kstc_info.FileObject;
5497 DeviceObject = IoGetRelatedDeviceObject(ConnObject);
5499 Irp = KsBuildTdiIrp(DeviceObject);
5503 /* release the chained mdl */
5504 ks_release_mdl(mdl, FALSE);
5506 Status = STATUS_INSUFFICIENT_RESOURCES;
5510 length = KsQueryMdlsSize(mdl);
5512 LASSERT((ULONG)len <= length);
5514 ks_get_tconn(tconn);
5520 KsTcpCompletionRoutine,
5522 (bBuffed ? NewMdl : mdl),
5523 (bBuffed ? (tflags | TDI_SEND_NON_BLOCKING) : tflags),
5527 Status = IoCallDriver(DeviceObject, Irp);
5530 ks_release_mdl(mdl, FALSE);
5534 if (!NT_SUCCESS(Status)) {
5535 cfs_enter_debugger();
5536 rc = cfs_error_code(Status);
5541 Status = STATUS_SUCCESS;
5546 if (InterlockedDecrement(&context->ReferCount) == 0) {
5547 Status = Irp->IoStatus.Status;
5549 Status = STATUS_PENDING;
5553 if (STATUS_PENDING == Status) {
5554 Status = KeWaitForSingleObject(
5562 if (NT_SUCCESS(Status)) {
5563 Status = Irp->IoStatus.Status;
5568 if (Status == STATUS_SUCCESS) {
5569 rc = (int)(Irp->IoStatus.Information);
5571 spin_lock(&tconn->kstc_lock);
5572 KsTsduMgr->TotalBytes -= rc;
5573 spin_unlock(&tconn->kstc_lock);
5576 rc = cfs_error_code(Status);
5585 ks_release_mdl(NewMdl, FALSE);
5590 if (!NT_SUCCESS(Status)) {
5598 if (Status != STATUS_PENDING) {
5602 /* Freeing the Irp ... */
5610 if (!NT_SUCCESS(Status)) {
5612 spin_lock(&tconn->kstc_lock);
5614 KsTsduMgr->TotalBytes -= (ULONG)len;
5618 /* attach it to the TsduMgr list if the Tsdu is newly created. */
5621 list_del(&(KsTsdu->Link));
5622 KsTsduMgr->NumOfTsdu--;
5624 KsPutKsTsdu(KsTsdu);
5627 if ( (ulong_ptr)KsTsduBuf + sizeof(KS_TSDU_BUF) ==
5628 (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
5629 KsTsdu->LastOffset -= sizeof(KS_TSDU_BUF);
5630 KsTsduBuf->TsduType = 0;
5632 cfs_enter_debugger();
5633 KsTsduBuf->StartOffset = KsTsduBuf->DataLength;
5636 if ( (ulong_ptr)KsTsduDat + KsTsduDat->TotalLength ==
5637 (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
5638 KsTsdu->LastOffset -= KsTsduDat->TotalLength;
5639 KsTsduDat->TsduType = 0;
5641 cfs_enter_debugger();
5642 KsTsduDat->StartOffset = KsTsduDat->DataLength;
5648 spin_unlock(&tconn->kstc_lock);
5651 /* free the context if is not used at all */
5656 ks_put_tconn(tconn);
5663 * Receive data from the peer for a stream connection
5666 * tconn: tdi connection object
5667 * mdl: the mdl chain to contain the incoming data
5668 * len: length of the data
5669 * flags: flags of the receiving
5680 ksock_tconn_t * tconn,
5686 NTSTATUS Status = STATUS_SUCCESS;
5689 BOOLEAN bIsNonBlock;
5690 BOOLEAN bIsExpedited;
5693 PKS_TSDUMGR KsTsduMgr;
5695 PKS_TSDU_DAT KsTsduDat;
5696 PKS_TSDU_BUF KsTsduBuf;
5697 PKS_TSDU_MDL KsTsduMdl;
5701 ULONG BytesRecved = 0;
5704 bIsNonBlock = cfs_is_flag_set(flags, MSG_DONTWAIT);
5705 bIsExpedited = cfs_is_flag_set(flags, MSG_OOB);
5707 ks_get_tconn(tconn);
5713 spin_lock(&(tconn->kstc_lock));
5715 if ( tconn->kstc_type != kstt_sender &&
5716 tconn->kstc_type != kstt_child) {
5719 spin_unlock(&(tconn->kstc_lock));
5724 if (tconn->kstc_state != ksts_connected) {
5727 spin_unlock(&(tconn->kstc_lock));
5732 if (tconn->kstc_type == kstt_sender) {
5733 KsChain = &(tconn->sender.kstc_recv);
5735 LASSERT(tconn->kstc_type == kstt_child);
5736 KsChain = &(tconn->child.kstc_recv);
5740 KsTsduMgr = &(KsChain->Expedited);
5742 KsTsduMgr = &(KsChain->Normal);
5747 if (list_empty(&(KsTsduMgr->TsduList))) {
5750 // It's a notification event. We need reset it to
5751 // un-signaled state in case there no any tsdus.
5754 KeResetEvent(&(KsTsduMgr->Event));
5758 KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
5759 LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
5761 /* remove the KsTsdu from TsduMgr list to release the lock */
5762 list_del(&(KsTsdu->Link));
5763 KsTsduMgr->NumOfTsdu--;
5765 spin_unlock(&(tconn->kstc_lock));
5767 while ((ULONG)size > BytesRecved) {
5769 ULONG BytesCopied = 0;
5770 ULONG BytesToCopy = 0;
5771 ULONG StartOffset = 0;
5773 KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5774 KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5775 KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
5777 if ( TSDU_TYPE_DAT == KsTsduDat->TsduType ||
5778 TSDU_TYPE_BUF == KsTsduBuf->TsduType ) {
5782 // Data Tsdu Unit ...
5785 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
5787 if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
5788 /* data is not ready yet*/
5789 KeResetEvent(&(KsTsduMgr->Event));
5790 printk("ks_recv_mdl: KsTsduDat (%xh) is not ready yet !!!!!!!\n", KsTsduDat);
5794 Buffer = &KsTsduDat->Data[0];
5795 StartOffset = KsTsduDat->StartOffset;
5796 if (KsTsduDat->DataLength - KsTsduDat->StartOffset > size - BytesRecved) {
5797 /* Recvmsg requst could be statisfied ... */
5798 BytesToCopy = size - BytesRecved;
5800 BytesToCopy = KsTsduDat->DataLength - KsTsduDat->StartOffset;
5805 if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
5806 /* data is not ready yet*/
5807 KeResetEvent(&(KsTsduMgr->Event));
5808 DbgPrint("ks_recv_mdl: KsTsduBuf (%xh) is not ready yet !!!!!!!\n", KsTsduBuf);
5812 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
5813 Buffer = KsTsduBuf->UserBuffer;
5814 StartOffset = KsTsduBuf->StartOffset;
5816 if (KsTsduBuf->DataLength - KsTsduBuf->StartOffset > size - BytesRecved) {
5817 /* Recvmsg requst could be statisfied ... */
5818 BytesToCopy = size - BytesRecved;
5820 BytesToCopy = KsTsduBuf->DataLength - KsTsduBuf->StartOffset;
5824 if (BytesToCopy > 0) {
5825 Status = TdiCopyBufferToMdl(
5834 if (NT_SUCCESS(Status)) {
5836 if (BytesToCopy != BytesCopied) {
5837 cfs_enter_debugger();
5840 BytesRecved += BytesCopied;
5841 RecvedOnce += BytesCopied;
5845 cfs_enter_debugger();
5847 if (STATUS_BUFFER_OVERFLOW == Status) {
5852 if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
5854 KsTsduDat->StartOffset += BytesCopied;
5856 if (KsTsduDat->StartOffset == KsTsduDat->DataLength) {
5857 KsTsdu->StartOffset += KsTsduDat->TotalLength;
5862 ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
5863 KsTsduBuf->StartOffset += BytesCopied;
5864 if (KsTsduBuf->StartOffset == KsTsduBuf->DataLength) {
5865 KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
5866 /* now we need release the buf to system pool */
5867 ExFreePool(KsTsduBuf->UserBuffer);
5871 } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
5874 // MDL Tsdu Unit ...
5877 if (KsTsduMdl->DataLength > size - BytesRecved) {
5879 /* Recvmsg requst could be statisfied ... */
5881 BytesToCopy = size - BytesRecved;
5885 BytesToCopy = KsTsduMdl->DataLength;
5888 Status = KsCopyMdlChainToMdlChain(
5890 KsTsduMdl->StartOffset,
5897 if (NT_SUCCESS(Status)) {
5899 if (BytesToCopy != BytesCopied) {
5900 cfs_enter_debugger();
5903 KsTsduMdl->StartOffset += BytesCopied;
5904 KsTsduMdl->DataLength -= BytesCopied;
5906 BytesRecved += BytesCopied;
5907 RecvedOnce += BytesCopied;
5909 cfs_enter_debugger();
5912 if (0 == KsTsduMdl->DataLength) {
5915 // Call TdiReturnChainedReceives to release the Tsdu memory
5918 TdiReturnChainedReceives(
5919 &(KsTsduMdl->Descriptor),
5922 KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
5926 printk("ks_recv_mdl: unknown tsdu slot: slot = %x type = %x Start= %x\n",
5927 KsTsduDat, KsTsduDat->TsduType, KsTsduDat->StartOffset, KsTsduDat->DataLength);
5928 printk(" Tsdu = %x Magic=%x: Start = %x Last = %x Length = %x",
5929 KsTsdu, KsTsdu->Magic, KsTsdu->StartOffset, KsTsdu->LastOffset, KsTsdu->TotalLength);
5930 cfs_enter_debugger();
5933 if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
5936 // KsTsdu is empty now, we need free it ...
5939 KsPutKsTsdu(KsTsdu);
5946 spin_lock(&(tconn->kstc_lock));
5948 /* we need attach the KsTsdu to the list header */
5950 KsTsduMgr->NumOfTsdu++;
5951 list_add(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
5952 } else if ((ULONG)size > BytesRecved) {
5957 if (KsTsduMgr->TotalBytes < RecvedOnce) {
5958 cfs_enter_debugger();
5959 KsTsduMgr->TotalBytes = 0;
5961 KsTsduMgr->TotalBytes -= RecvedOnce;
5964 spin_unlock(&(tconn->kstc_lock));
5966 if (NT_SUCCESS(Status)) {
5968 if ((BytesRecved < (ulong_ptr)size) && (!bIsNonBlock)) {
5970 KeWaitForSingleObject(
5971 &(KsTsduMgr->Event),
5981 if (bIsNonBlock && (BytesRecved == 0)) {
5990 ks_put_tconn(tconn);
5993 KsPrint((1, "ks_recv_mdl: recvieving %d bytes ...\n", rc));
5995 KsPrint((0, "ks_recv_mdl: recvieving error code = %d Stauts = %xh ...\n", rc, Status));
5998 /* release the chained mdl */
5999 ks_release_mdl(mdl, FALSE);
6007 * initialize the global data in ksockal_data
6013 * int: ks error code
6024 /* initialize tconn related globals */
6025 RtlZeroMemory(&ks_data, sizeof(ks_data_t));
6027 spin_lock_init(&ks_data.ksnd_tconn_lock);
6028 CFS_INIT_LIST_HEAD(&ks_data.ksnd_tconns);
6029 cfs_init_event(&ks_data.ksnd_tconn_exit, TRUE, FALSE);
6031 ks_data.ksnd_tconn_slab = cfs_mem_cache_create(
6032 "tcon", sizeof(ksock_tconn_t) , 0, 0);
6034 if (!ks_data.ksnd_tconn_slab) {
6039 /* initialize tsdu related globals */
6041 spin_lock_init(&ks_data.ksnd_tsdu_lock);
6042 CFS_INIT_LIST_HEAD(&ks_data.ksnd_freetsdus);
6043 ks_data.ksnd_tsdu_size = TDINAL_TSDU_DEFAULT_SIZE; /* 64k */
6044 ks_data.ksnd_tsdu_slab = cfs_mem_cache_create(
6045 "tsdu", ks_data.ksnd_tsdu_size, 0, 0);
6047 if (!ks_data.ksnd_tsdu_slab) {
6049 cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
6050 ks_data.ksnd_tconn_slab = NULL;
6054 /* initialize daemon related globals */
6056 spin_lock_init(&ks_data.ksnd_daemon_lock);
6057 CFS_INIT_LIST_HEAD(&ks_data.ksnd_daemons);
6058 cfs_init_event(&ks_data.ksnd_daemon_exit, TRUE, FALSE);
6060 KsRegisterPnpHandlers();
6070 * finalize the global data in ksockal_data
6076 * int: ks error code
6085 PKS_TSDU KsTsdu = NULL;
6086 struct list_head * list = NULL;
6088 /* clean up the pnp handler and address slots */
6089 KsDeregisterPnpHandlers();
6091 /* we need wait until all the tconn are freed */
6092 spin_lock(&(ks_data.ksnd_tconn_lock));
6094 if (list_empty(&(ks_data.ksnd_tconns))) {
6095 cfs_wake_event(&ks_data.ksnd_tconn_exit);
6097 spin_unlock(&(ks_data.ksnd_tconn_lock));
6099 /* now wait on the tconn exit event */
6100 cfs_wait_event(&ks_data.ksnd_tconn_exit, 0);
6102 /* it's safe to delete the tconn slab ... */
6103 cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
6104 ks_data.ksnd_tconn_slab = NULL;
6106 /* clean up all the tsud buffers in the free list */
6107 spin_lock(&(ks_data.ksnd_tsdu_lock));
6108 list_for_each (list, &ks_data.ksnd_freetsdus) {
6109 KsTsdu = list_entry (list, KS_TSDU, Link);
6112 ks_data.ksnd_tsdu_slab,
6115 spin_unlock(&(ks_data.ksnd_tsdu_lock));
6117 /* it's safe to delete the tsdu slab ... */
6118 cfs_mem_cache_destroy(ks_data.ksnd_tsdu_slab);
6119 ks_data.ksnd_tsdu_slab = NULL;
6121 /* good! it's smooth to do the cleaning up...*/
6125 * ks_create_child_tconn
6126 * Create the backlog child connection for a listener
6129 * parent: the listener daemon connection
6132 * the child connection or NULL in failure
6139 ks_create_child_tconn(
6140 ksock_tconn_t * parent
6144 ksock_tconn_t * backlog;
6146 /* allocate the tdi connecton object */
6147 backlog = ks_create_tconn();
6153 /* initialize the tconn as a child */
6154 ks_init_child(backlog);
6158 if (ks_bind_tconn(backlog, parent, 0, 0) < 0) {
6159 ks_free_tconn(backlog);
6164 /* open the connection object */
6165 status = KsOpenConnection(
6166 &(backlog->kstc_dev),
6168 &(backlog->child.kstc_info.Handle),
6169 &(backlog->child.kstc_info.FileObject)
6172 if (!NT_SUCCESS(status)) {
6174 ks_put_tconn(backlog);
6176 cfs_enter_debugger();
6180 /* associate it now ... */
6181 status = KsAssociateAddress(
6182 backlog->kstc_addr.Handle,
6183 backlog->child.kstc_info.FileObject
6186 if (!NT_SUCCESS(status)) {
6188 ks_put_tconn(backlog);
6190 cfs_enter_debugger();
6194 backlog->kstc_state = ksts_associated;
6202 * ks_replenish_backlogs(
6203 * to replenish the backlogs listening...
6206 * tconn: the parent listen tdi connect
6207 * nbacklog: number fo child connections in queue
6217 ks_replenish_backlogs(
6218 ksock_tconn_t * parent,
6222 ksock_tconn_t * backlog;
6225 /* calculate how many backlogs needed */
6226 if ( ( parent->listener.kstc_listening.num +
6227 parent->listener.kstc_accepted.num ) < nbacklog ) {
6228 n = nbacklog - ( parent->listener.kstc_listening.num +
6229 parent->listener.kstc_accepted.num );
6236 /* create the backlog child tconn */
6237 backlog = ks_create_child_tconn(parent);
6239 spin_lock(&(parent->kstc_lock));
6242 spin_lock(&backlog->kstc_lock);
6243 /* attch it into the listing list of daemon */
6244 list_add( &backlog->child.kstc_link,
6245 &parent->listener.kstc_listening.list );
6246 parent->listener.kstc_listening.num++;
6248 backlog->child.kstc_queued = TRUE;
6249 spin_unlock(&backlog->kstc_lock);
6251 cfs_enter_debugger();
6254 spin_unlock(&(parent->kstc_lock));
6260 * setup the listener tdi connection and make it listen
6261 * on the user specified ip address and port.
6264 * tconn: the parent listen tdi connect
6265 * nbacklog: number fo child connections in queue
6268 * ks error code >=: success; otherwise error.
6275 ks_start_listen(ksock_tconn_t *tconn, int nbacklog)
6279 /* now replenish the backlogs */
6280 ks_replenish_backlogs(tconn, nbacklog);
6282 /* set the event callback handlers */
6283 rc = ks_set_handlers(tconn);
6289 spin_lock(&(tconn->kstc_lock));
6290 tconn->listener.nbacklog = nbacklog;
6291 tconn->kstc_state = ksts_listening;
6292 cfs_set_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
6293 spin_unlock(&(tconn->kstc_lock));
6299 ks_stop_listen(ksock_tconn_t *tconn)
6301 struct list_head * list;
6302 ksock_tconn_t * backlog;
6304 /* reset all tdi event callbacks to NULL */
6305 ks_reset_handlers (tconn);
6307 spin_lock(&tconn->kstc_lock);
6309 cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
6311 /* cleanup all the listening backlog child connections */
6312 list_for_each (list, &(tconn->listener.kstc_listening.list)) {
6313 backlog = list_entry(list, ksock_tconn_t, child.kstc_link);
6315 /* destory and free it */
6316 ks_put_tconn(backlog);
6319 spin_unlock(&tconn->kstc_lock);
6321 /* wake up it from the waiting on new incoming connections */
6322 KeSetEvent(&tconn->listener.kstc_accept_event, 0, FALSE);
6324 /* free the listening daemon tconn */
6325 ks_put_tconn(tconn);
6330 * ks_wait_child_tconn
6331 * accept a child connection from peer
6334 * parent: the daemon tdi connection listening
6335 * child: to contain the accepted connection
6345 ks_wait_child_tconn(
6346 ksock_tconn_t * parent,
6347 ksock_tconn_t ** child
6350 struct list_head * tmp;
6351 ksock_tconn_t * backlog = NULL;
6353 ks_replenish_backlogs(parent, parent->listener.nbacklog);
6355 spin_lock(&(parent->kstc_lock));
6357 if (parent->listener.kstc_listening.num <= 0) {
6358 spin_unlock(&(parent->kstc_lock));
6364 /* check the listening queue and try to search the accepted connecton */
6366 list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
6367 backlog = list_entry (tmp, ksock_tconn_t, child.kstc_link);
6369 spin_lock(&(backlog->kstc_lock));
6371 if (backlog->child.kstc_accepted) {
6373 LASSERT(backlog->kstc_state == ksts_connected);
6374 LASSERT(backlog->child.kstc_busy);
6376 list_del(&(backlog->child.kstc_link));
6377 list_add(&(backlog->child.kstc_link),
6378 &(parent->listener.kstc_accepted.list));
6379 parent->listener.kstc_accepted.num++;
6380 parent->listener.kstc_listening.num--;
6381 backlog->child.kstc_queueno = 1;
6383 spin_unlock(&(backlog->kstc_lock));
6387 spin_unlock(&(backlog->kstc_lock));
6392 spin_unlock(&(parent->kstc_lock));
6394 /* we need wait until new incoming connections are requested
6395 or the case of shuting down the listenig daemon thread */
6396 if (backlog == NULL) {
6400 Status = KeWaitForSingleObject(
6401 &(parent->listener.kstc_accept_event),
6408 spin_lock(&(parent->kstc_lock));
6410 /* check whether it's exptected to exit ? */
6411 if (!cfs_is_flag_set(parent->kstc_flags, KS_TCONN_DAEMON_STARTED)) {
6412 spin_unlock(&(parent->kstc_lock));
6419 /* query the local ip address of the connection */
6420 ks_query_local_ipaddr(backlog);
6428 int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask)
6430 ks_addr_slot_t * slot = NULL;
6431 PLIST_ENTRY list = NULL;
6433 spin_lock(&ks_data.ksnd_addrs_lock);
6435 list = ks_data.ksnd_addrs_list.Flink;
6436 while (list != &ks_data.ksnd_addrs_list) {
6437 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
6438 if (_stricmp(name, &slot->iface[0]) == 0) {
6440 *ip = slot->ip_addr;
6441 *mask = slot->netmask;
6448 spin_unlock(&ks_data.ksnd_addrs_lock);
6450 return (int)(slot == NULL);
6453 int libcfs_ipif_enumerate(char ***names)
6455 ks_addr_slot_t * slot = NULL;
6456 PLIST_ENTRY list = NULL;
6459 spin_lock(&ks_data.ksnd_addrs_lock);
6461 *names = cfs_alloc(sizeof(char *) * ks_data.ksnd_naddrs, CFS_ALLOC_ZERO);
6462 if (*names == NULL) {
6466 list = ks_data.ksnd_addrs_list.Flink;
6467 while (list != &ks_data.ksnd_addrs_list) {
6468 slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
6470 (*names)[nips++] = slot->iface;
6471 cfs_assert(nips <= ks_data.ksnd_naddrs);
6474 cfs_assert(nips == ks_data.ksnd_naddrs);
6478 spin_unlock(&ks_data.ksnd_addrs_lock);
6482 void libcfs_ipif_free_enumeration(char **names, int n)
6489 int libcfs_sock_listen(struct socket **sockp, __u32 ip, int port, int backlog)
6492 ksock_tconn_t * parent;
6494 parent = ks_create_tconn();
6500 /* initialize the tconn as a listener */
6501 ks_init_listener(parent);
6503 /* bind the daemon->tconn */
6504 rc = ks_bind_tconn(parent, NULL, ip, (unsigned short)port);
6507 ks_free_tconn(parent);
6511 /* create listening children and make it to listen state*/
6512 rc = ks_start_listen(parent, backlog);
6514 ks_stop_listen(parent);
6525 int libcfs_sock_accept(struct socket **newsockp, struct socket *sock)
6527 /* wait for incoming connecitons */
6528 return ks_wait_child_tconn(sock, newsockp);
6531 void libcfs_sock_abort_accept(struct socket *sock)
6533 LASSERT(sock->kstc_type == kstt_listener);
6535 spin_lock(&(sock->kstc_lock));
6537 /* clear the daemon flag */
6538 cfs_clear_flag(sock->kstc_flags, KS_TCONN_DAEMON_STARTED);
6540 /* wake up it from the waiting on new incoming connections */
6541 KeSetEvent(&sock->listener.kstc_accept_event, 0, FALSE);
6543 spin_unlock(&(sock->kstc_lock));
6547 * libcfs_sock_connect
6548 * build a conntion between local ip/port and the peer ip/port.
6551 * laddr: local ip address
6552 * lport: local port number
6553 * paddr: peer's ip address
6554 * pport: peer's port number
6557 * int: return code ...
6564 int libcfs_sock_connect(struct socket **sockp, int *fatal,
6565 __u32 local_ip, int local_port,
6566 __u32 peer_ip, int peer_port)
6568 ksock_tconn_t * tconn = NULL;
6573 KsPrint((1, "libcfs_sock_connect: connecting to %x:%d with %x:%d...\n",
6574 peer_ip, peer_port, local_ip, local_port ));
6576 /* create the tdi connecion structure */
6577 tconn = ks_create_tconn();
6583 /* initialize the tdi sender connection */
6584 ks_init_sender(tconn);
6586 /* bind the local ip address with the tconn */
6587 rc = ks_bind_tconn(tconn, NULL, local_ip, (unsigned short)local_port);
6589 KsPrint((0, "libcfs_sock_connect: failed to bind address %x:%d...\n",
6590 local_ip, local_port ));
6591 ks_free_tconn(tconn);
6595 /* connect to the remote peer */
6596 rc = ks_build_tconn(tconn, peer_ip, (unsigned short)peer_port);
6598 KsPrint((0, "libcfs_sock_connect: failed to connect %x:%d ...\n",
6599 peer_ip, peer_port ));
6601 ks_put_tconn(tconn);
6612 int libcfs_sock_setbuf(struct socket *socket, int txbufsize, int rxbufsize)
6617 int libcfs_sock_getbuf(struct socket *socket, int *txbufsize, int *rxbufsize)
6622 int libcfs_sock_getaddr(struct socket *socket, int remote, __u32 *ip, int *port)
6624 PTRANSPORT_ADDRESS taddr = NULL;
6626 spin_lock(&socket->kstc_lock);
6628 if (socket->kstc_type == kstt_sender) {
6629 taddr = socket->sender.kstc_info.Remote;
6630 } else if (socket->kstc_type == kstt_child) {
6631 taddr = socket->child.kstc_info.Remote;
6634 taddr = &(socket->kstc_addr.Tdi);
6638 PTDI_ADDRESS_IP addr = (PTDI_ADDRESS_IP)(&(taddr->Address[0].Address));
6640 *ip = ntohl (addr->in_addr);
6642 *port = ntohs (addr->sin_port);
6644 spin_unlock(&socket->kstc_lock);
6648 spin_unlock(&socket->kstc_lock);
6652 int libcfs_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
6659 while (nob > offset) {
6661 /* lock the user buffer */
6662 rc = ks_lock_buffer( (char *)buffer + offset,
6663 FALSE, nob - offset, IoReadAccess, &mdl );
6669 /* send out the whole mdl */
6670 rc = ks_send_mdl( sock, NULL, mdl, nob - offset, 0 );
6682 int libcfs_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
6689 while (nob > offset) {
6691 /* lock the user buffer */
6692 rc = ks_lock_buffer( (char *)buffer + offset,
6693 FALSE, nob - offset, IoWriteAccess, &mdl );
6699 /* recv the requested buffer */
6700 rc = ks_recv_mdl( sock, mdl, nob - offset, 0 );
6712 void libcfs_sock_release(struct socket *sock)
6714 if (sock->kstc_type == kstt_listener &&
6715 sock->kstc_state == ksts_listening) {
6716 ks_stop_listen(sock);