|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1989-1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: uframes.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains a routine called StProcessConnectionless, ! 12: that gets control from routines in IND.C when a connectionless ! 13: frame is received. ! 14: ! 15: Environment: ! 16: ! 17: Kernel mode, DISPATCH_LEVEL. ! 18: ! 19: Revision History: ! 20: ! 21: --*/ ! 22: ! 23: #include "st.h" ! 24: ! 25: ! 26: ! 27: NTSTATUS ! 28: StIndicateDatagram( ! 29: IN PDEVICE_CONTEXT DeviceContext, ! 30: IN PTP_ADDRESS Address, ! 31: IN PUCHAR Header, ! 32: IN ULONG Length ! 33: ) ! 34: ! 35: /*++ ! 36: ! 37: Routine Description: ! 38: ! 39: This routine processes an incoming DATAGRAM or DATAGRAM_BROADCAST frame. ! 40: BROADCAST and normal datagrams have the same receive logic, except ! 41: for broadcast datagrams Address will be the broadcast address. ! 42: ! 43: When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of ! 44: this routine will continue to call us for each address for the device ! 45: context. When we return STATUS_SUCCESS, the caller will switch to the ! 46: next address. When we return any other status code, including ! 47: STATUS_ABANDONED, the caller will stop distributing the frame. ! 48: ! 49: Arguments: ! 50: ! 51: DeviceContext - Pointer to our device context. ! 52: ! 53: Address - Pointer to the transport address object. ! 54: ! 55: StHeader - Pointer to a buffer that contains the receive datagram. ! 56: The first byte of information is the ST header. ! 57: ! 58: Length - The length of the MDL pointed to by StHeader. ! 59: ! 60: Return Value: ! 61: ! 62: NTSTATUS - status of operation. ! 63: ! 64: --*/ ! 65: ! 66: { ! 67: NTSTATUS status; ! 68: PLIST_ENTRY p, q; ! 69: PIRP irp; ! 70: PIO_STACK_LOCATION irpSp; ! 71: PTP_REQUEST Request; ! 72: ULONG IndicateBytesCopied, MdlBytesCopied; ! 73: KIRQL oldirql; ! 74: TA_NETBIOS_ADDRESS SourceName; ! 75: TA_NETBIOS_ADDRESS DestinationName; ! 76: PTDI_CONNECTION_INFORMATION remoteInformation; ! 77: ULONG returnLength; ! 78: PTP_ADDRESS_FILE addressFile, prevaddressFile; ! 79: PST_HEADER StHeader; ! 80: ! 81: // ! 82: // If this datagram wasn't big enough for a transport header, then don't ! 83: // let the caller look at any data. ! 84: // ! 85: ! 86: if (Length < sizeof(ST_HEADER)) { ! 87: return STATUS_ABANDONED; ! 88: } ! 89: ! 90: // ! 91: // Update our statistics. ! 92: // ! 93: ! 94: ++DeviceContext->DatagramsReceived; ! 95: ADD_TO_LARGE_INTEGER( ! 96: &DeviceContext->DatagramBytesReceived, ! 97: Length - sizeof(ST_HEADER), ! 98: &DeviceContext->StatisticsSpinLock); ! 99: ! 100: ! 101: // ! 102: // Call the client's ReceiveDatagram indication handler. He may ! 103: // want to accept the datagram that way. ! 104: // ! 105: ! 106: StHeader = (PST_HEADER)Header; ! 107: ! 108: TdiBuildNetbiosAddress (StHeader->Source, FALSE, &SourceName); ! 109: TdiBuildNetbiosAddress (StHeader->Destination, FALSE, &DestinationName); ! 110: ! 111: ! 112: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 113: ! 114: // ! 115: // Find the first open address file in the list. ! 116: // ! 117: ! 118: p = Address->AddressFileDatabase.Flink; ! 119: while (p != &Address->AddressFileDatabase) { ! 120: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); ! 121: if (addressFile->State != ADDRESSFILE_STATE_OPEN) { ! 122: p = p->Flink; ! 123: continue; ! 124: } ! 125: StReferenceAddressFile(addressFile); ! 126: break; ! 127: } ! 128: ! 129: while (p != &Address->AddressFileDatabase) { ! 130: ! 131: // ! 132: // do we have a datagram receive request outstanding? If so, we will ! 133: // satisfy it first. ! 134: // ! 135: // NOTE: We should check if this receive dataframs is for ! 136: // a specific address. ! 137: // ! 138: ! 139: q = RemoveHeadList (&addressFile->ReceiveDatagramQueue); ! 140: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 141: ! 142: if (q != &addressFile->ReceiveDatagramQueue) { ! 143: ! 144: Request = CONTAINING_RECORD (q, TP_REQUEST, Linkage); ! 145: ! 146: // ! 147: // Copy the actual user data. ! 148: // ! 149: ! 150: MdlBytesCopied = 0; ! 151: ! 152: status = TdiCopyBufferToMdl ( ! 153: StHeader, ! 154: sizeof(ST_HEADER), // offset ! 155: Length - sizeof(ST_HEADER), // length ! 156: Request->IoRequestPacket->MdlAddress, ! 157: 0, ! 158: &MdlBytesCopied); ! 159: ! 160: irpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket); ! 161: remoteInformation = ! 162: ((PTDI_REQUEST_KERNEL_RECEIVEDG)(&irpSp->Parameters))-> ! 163: ReturnDatagramInformation; ! 164: if (remoteInformation != NULL) { ! 165: try { ! 166: if (remoteInformation->RemoteAddressLength != 0) { ! 167: if (remoteInformation->RemoteAddressLength >= ! 168: sizeof (TA_NETBIOS_ADDRESS)) { ! 169: ! 170: RtlCopyMemory ( ! 171: (PTA_NETBIOS_ADDRESS)remoteInformation->RemoteAddress, ! 172: &SourceName, ! 173: sizeof (TA_NETBIOS_ADDRESS)); ! 174: ! 175: returnLength = sizeof(TA_NETBIOS_ADDRESS); ! 176: remoteInformation->RemoteAddressLength = returnLength; ! 177: ! 178: } else { ! 179: ! 180: RtlCopyMemory ( ! 181: (PTA_NETBIOS_ADDRESS)remoteInformation->RemoteAddress, ! 182: &SourceName, ! 183: remoteInformation->RemoteAddressLength); ! 184: ! 185: returnLength = remoteInformation->RemoteAddressLength; ! 186: remoteInformation->RemoteAddressLength = returnLength; ! 187: ! 188: } ! 189: ! 190: } else { ! 191: ! 192: returnLength = 0; ! 193: } ! 194: ! 195: status = STATUS_SUCCESS; ! 196: ! 197: } except (EXCEPTION_EXECUTE_HANDLER) { ! 198: ! 199: returnLength = 0; ! 200: status = GetExceptionCode (); ! 201: ! 202: } ! 203: ! 204: } ! 205: ! 206: StCompleteRequest (Request, STATUS_SUCCESS, MdlBytesCopied); ! 207: ! 208: } else { ! 209: ! 210: // ! 211: // no receive datagram requests; is there a kernel client? ! 212: // ! 213: ! 214: if (addressFile->RegisteredReceiveDatagramHandler) { ! 215: ! 216: IndicateBytesCopied = 0; ! 217: ! 218: // ! 219: // Note that we can always set the COPY_LOOKAHEAD ! 220: // flag because we are indicating from our own ! 221: // buffer, not directly from a lookahead indication. ! 222: // ! 223: ! 224: status = (*addressFile->ReceiveDatagramHandler)( ! 225: addressFile->ReceiveDatagramHandlerContext, ! 226: sizeof (TA_NETBIOS_ADDRESS), ! 227: &SourceName, ! 228: 0, ! 229: NULL, ! 230: TDI_RECEIVE_COPY_LOOKAHEAD, ! 231: Length - sizeof(ST_HEADER), // indicated ! 232: Length - sizeof(ST_HEADER), // available ! 233: &IndicateBytesCopied, ! 234: Header + sizeof(ST_HEADER), ! 235: &irp); ! 236: ! 237: if (status == STATUS_SUCCESS) { ! 238: ! 239: // ! 240: // The client accepted the datagram and so we're done. ! 241: // ! 242: ! 243: } else if (status == STATUS_DATA_NOT_ACCEPTED) { ! 244: ! 245: // ! 246: // The client did not accept the datagram and we need to satisfy ! 247: // a TdiReceiveDatagram, if possible. ! 248: // ! 249: ! 250: status = STATUS_MORE_PROCESSING_REQUIRED; ! 251: ! 252: } else if (status == STATUS_MORE_PROCESSING_REQUIRED) { ! 253: ! 254: // ! 255: // The client returned an IRP that we should queue up to the ! 256: // address to satisfy the request. ! 257: // ! 258: ! 259: irp->IoStatus.Status = STATUS_PENDING; // init status information. ! 260: irp->IoStatus.Information = 0; ! 261: irpSp = IoGetCurrentIrpStackLocation (irp); // get current stack loctn. ! 262: if ((irpSp->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL) || ! 263: (irpSp->MinorFunction != TDI_RECEIVE_DATAGRAM)) { ! 264: irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; ! 265: return status; ! 266: } ! 267: ! 268: // ! 269: // Now copy the actual user data. ! 270: // ! 271: ! 272: MdlBytesCopied = 0; ! 273: ! 274: status = TdiCopyBufferToMdl ( ! 275: StHeader, ! 276: sizeof(ST_HEADER) + IndicateBytesCopied, ! 277: Length - sizeof(ST_HEADER) - IndicateBytesCopied, ! 278: irp->MdlAddress, ! 279: 0, ! 280: &MdlBytesCopied); ! 281: ! 282: irp->IoStatus.Information = MdlBytesCopied; ! 283: irp->IoStatus.Status = status; ! 284: IoCompleteRequest (irp, IO_NETWORK_INCREMENT); ! 285: } ! 286: } ! 287: } ! 288: ! 289: // ! 290: // Save this to dereference it later. ! 291: // ! 292: ! 293: prevaddressFile = addressFile; ! 294: ! 295: // ! 296: // Reference the next address file on the list, so it ! 297: // stays around. ! 298: // ! 299: ! 300: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 301: ! 302: p = p->Flink; ! 303: while (p != &Address->AddressFileDatabase) { ! 304: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); ! 305: if (addressFile->State != ADDRESSFILE_STATE_OPEN) { ! 306: p = p->Flink; ! 307: continue; ! 308: } ! 309: StReferenceAddressFile(addressFile); ! 310: break; ! 311: } ! 312: ! 313: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 314: ! 315: // ! 316: // Now dereference the previous address file with ! 317: // the lock released. ! 318: // ! 319: ! 320: StDereferenceAddressFile (prevaddressFile); ! 321: ! 322: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 323: ! 324: } // end of while loop ! 325: ! 326: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 327: ! 328: return status; // to dispatcher. ! 329: } /* StIndicateDatagram */ ! 330: ! 331: ! 332: NTSTATUS ! 333: StProcessConnect( ! 334: IN PDEVICE_CONTEXT DeviceContext, ! 335: IN PTP_ADDRESS Address, ! 336: IN PST_HEADER Header, ! 337: IN PHARDWARE_ADDRESS SourceAddress, ! 338: IN PUCHAR SourceRouting, ! 339: IN UINT SourceRoutingLength ! 340: ) ! 341: ! 342: /*++ ! 343: ! 344: Routine Description: ! 345: ! 346: This routine processes an incoming connect frame. It scans for ! 347: posted listens, otherwise it indicates to connect handlers ! 348: on this address if they are registered. ! 349: ! 350: Arguments: ! 351: ! 352: DeviceContext - Pointer to our device context. ! 353: ! 354: Address - Pointer to the transport address object. ! 355: ! 356: Header - Pointer to the ST header of the frame. ! 357: ! 358: SourceAddress - Pointer to the source hardware address in the received ! 359: frame. ! 360: ! 361: SourceRouting - Pointer to the source routing information in ! 362: the frame. ! 363: ! 364: SourceRoutingLength - Length of the source routing information. ! 365: ! 366: Return Value: ! 367: ! 368: NTSTATUS - status of operation. ! 369: ! 370: --*/ ! 371: ! 372: { ! 373: KIRQL oldirql, oldirql1, cancelirql; ! 374: NTSTATUS status; ! 375: PTP_CONNECTION Connection; ! 376: BOOLEAN ConnectIndicationBlocked = FALSE; ! 377: PLIST_ENTRY p; ! 378: BOOLEAN UsedListeningConnection = FALSE; ! 379: PTP_ADDRESS_FILE addressFile, prevaddressFile; ! 380: ! 381: PTP_REQUEST request; ! 382: PIO_STACK_LOCATION irpSp; ! 383: ULONG returnLength; ! 384: PTDI_CONNECTION_INFORMATION remoteInformation; ! 385: TA_NETBIOS_ADDRESS TempAddress; ! 386: PIRP acceptIrp; ! 387: ! 388: CONNECTION_CONTEXT connectionContext; ! 389: ! 390: // ! 391: // If we are just registering or deregistering this address, then don't ! 392: // allow state changes. Just throw the packet away, and let the frame ! 393: // distributor try the next address. ! 394: // ! 395: ! 396: if (Address->Flags & (ADDRESS_FLAGS_REGISTERING | ADDRESS_FLAGS_DEREGISTERING)) { ! 397: return STATUS_SUCCESS; ! 398: } ! 399: ! 400: // ! 401: // This is an incoming connection request. If we have a listening ! 402: // connection on this address, then continue with the connection setup. ! 403: // If there is no outstanding listen, then indicate any kernel mode ! 404: // clients that want to know about this frame. If a listen was posted, ! 405: // then a connection has already been set up for it. ! 406: // ! 407: ! 408: // ! 409: // First, check if we already have an active connection with ! 410: // this remote on this address. If so, we ignore this ! 411: // (NOTE: This is not the correct behaviour for a real ! 412: // transport). ! 413: // ! 414: ! 415: // ! 416: // If successful this adds a reference. ! 417: // ! 418: ! 419: if (Connection = StLookupRemoteName(Address, Header->Source)) { ! 420: ! 421: StDereferenceConnection ("Lookup done", Connection); ! 422: return STATUS_ABANDONED; ! 423: ! 424: } ! 425: ! 426: // If successful, this adds a reference which is removed before ! 427: // this function returns. ! 428: ! 429: Connection = StLookupListeningConnection (Address); ! 430: if (Connection == NULL) { ! 431: ! 432: // ! 433: // not having a listening connection is not reason to bail out here. ! 434: // we need to indicate to the user that a connect attempt occurred, ! 435: // and see if there is a desire to use this connection. We ! 436: // indicate in order to all address files that are ! 437: // using this address. ! 438: // ! 439: // If we already have an indication pending on this address, ! 440: // we ignore this frame (the NAME_QUERY may have come from ! 441: // a different address, but we can't know that). Also, if ! 442: // there is already an active connection on this remote ! 443: // name, then we ignore the frame. ! 444: // ! 445: ! 446: ! 447: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 448: ! 449: p = Address->AddressFileDatabase.Flink; ! 450: while (p != &Address->AddressFileDatabase) { ! 451: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); ! 452: if (addressFile->State != ADDRESSFILE_STATE_OPEN) { ! 453: p = p->Flink; ! 454: continue; ! 455: } ! 456: StReferenceAddressFile(addressFile); ! 457: break; ! 458: } ! 459: ! 460: while (p != &Address->AddressFileDatabase) { ! 461: ! 462: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 463: ! 464: if ((addressFile->RegisteredConnectionHandler == TRUE) && ! 465: (!addressFile->ConnectIndicationInProgress)) { ! 466: ! 467: ! 468: TdiBuildNetbiosAddress ( ! 469: Header->Source, ! 470: FALSE, ! 471: &TempAddress); ! 472: ! 473: addressFile->ConnectIndicationInProgress = TRUE; ! 474: ! 475: // ! 476: // we have a connection handler, now indicate that a connection ! 477: // attempt occurred. ! 478: // ! 479: ! 480: status = (addressFile->ConnectionHandler)( ! 481: addressFile->ConnectionHandlerContext, ! 482: sizeof (TDI_ADDRESS_NETBIOS), ! 483: &TempAddress, ! 484: 0, ! 485: NULL, ! 486: 0, ! 487: NULL, ! 488: &connectionContext, ! 489: &acceptIrp); ! 490: ! 491: if (status == STATUS_MORE_PROCESSING_REQUIRED) { ! 492: ! 493: // the user has connected a currently open connection, but ! 494: // we have to figure out which one it is. ! 495: // ! 496: ! 497: // ! 498: // If successful this adds a reference of type LISTENING ! 499: // (the same what StLookupListeningConnection adds). ! 500: // ! 501: ! 502: Connection = StLookupConnectionByContext ( ! 503: Address, ! 504: connectionContext); ! 505: ! 506: if (Connection == NULL) { ! 507: ! 508: // ! 509: // BUGBUG: We have to tell the client that ! 510: // his connection is bogus (or has this ! 511: // already happened??). ! 512: // ! 513: ! 514: StPrint0("MORE_PROCESSING_REQUIRED, connection not found\n"); ! 515: addressFile->ConnectIndicationInProgress = FALSE; ! 516: acceptIrp->IoStatus.Status = STATUS_INVALID_CONNECTION; ! 517: IoCompleteRequest (acceptIrp, IO_NETWORK_INCREMENT); ! 518: ! 519: goto whileend; // try next address file ! 520: ! 521: } else { ! 522: ! 523: if (Connection->AddressFile->Address != Address) { ! 524: addressFile->ConnectIndicationInProgress = FALSE; ! 525: ! 526: StPrint0("MORE_PROCESSING_REQUIRED, address wrong\n"); ! 527: StStopConnection (Connection, STATUS_INVALID_ADDRESS); ! 528: StDereferenceConnection("Bad Address", Connection); ! 529: Connection = NULL; ! 530: acceptIrp->IoStatus.Status = STATUS_INVALID_CONNECTION; ! 531: IoCompleteRequest (acceptIrp, IO_NETWORK_INCREMENT); ! 532: ! 533: goto whileend; // try next address file ! 534: } ! 535: ! 536: // ! 537: // OK, we have a valid connection. If the response to ! 538: // this connection was disconnect, we need to reject ! 539: // the connection request and return. If it was accept ! 540: // or not specified (to be done later), we simply ! 541: // fall through and continue processing on the U Frame. ! 542: // ! 543: ! 544: ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql1); ! 545: if ((Connection->Flags2 & CONNECTION_FLAGS2_DISCONNECT) != 0) { ! 546: ! 547: Connection->Flags2 &= ~CONNECTION_FLAGS2_DISCONNECT; ! 548: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql1); ! 549: StPrint0("MORE_PROCESSING_REQUIRED, disconnect\n"); ! 550: addressFile->ConnectIndicationInProgress = FALSE; ! 551: StDereferenceConnection("Disconnecting", Connection); ! 552: Connection = NULL; ! 553: acceptIrp->IoStatus.Status = STATUS_INVALID_CONNECTION; ! 554: IoCompleteRequest (acceptIrp, IO_NETWORK_INCREMENT); ! 555: ! 556: goto whileend; // try next address file ! 557: } ! 558: ! 559: } ! 560: ! 561: // ! 562: // This connection is ready. ! 563: // ! 564: ! 565: Connection->Flags &= ~CONNECTION_FLAGS_STOPPING; ! 566: Connection->Status = STATUS_PENDING; ! 567: Connection->Flags2 |= CONNECTION_FLAGS2_ACCEPTED; ! 568: ! 569: Connection->Flags |= CONNECTION_FLAGS_READY; ! 570: INCREMENT_COUNTER (Connection->Provider, OpenConnections); ! 571: ! 572: Connection->Flags2 |= CONNECTION_FLAGS2_REQ_COMPLETED; ! 573: ! 574: StReferenceConnection("Indication completed", Connection); ! 575: ! 576: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql1); ! 577: ! 578: // ! 579: // Make a note that we have to set ! 580: // addressFile->ConnectIndicationInProgress to ! 581: // FALSE once the address is safely stored ! 582: // in the connection. ! 583: // ! 584: ! 585: ConnectIndicationBlocked = TRUE; ! 586: StDereferenceAddressFile (addressFile); ! 587: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 588: break; // exit the while ! 589: ! 590: } else if (status == STATUS_INSUFFICIENT_RESOURCES) { ! 591: ! 592: // ! 593: // we know the address, but can't create a connection to ! 594: // use on it. This gets passed to the network as a response ! 595: // saying I'm here, but can't help. ! 596: // ! 597: ! 598: addressFile->ConnectIndicationInProgress = FALSE; ! 599: ! 600: StDereferenceAddressFile (addressFile); ! 601: return STATUS_ABANDONED; ! 602: ! 603: } else { ! 604: ! 605: addressFile->ConnectIndicationInProgress = FALSE; ! 606: goto whileend; // try next address file ! 607: ! 608: } // end status ifs ! 609: ! 610: } else { ! 611: ! 612: goto whileend; // try next address file ! 613: ! 614: } // end no indication handler ! 615: ! 616: whileend: ! 617: // ! 618: // Jumping here is like a continue, except that the ! 619: // addressFile pointer is advanced correctly. ! 620: // ! 621: ! 622: // ! 623: // Save this to dereference it later. ! 624: // ! 625: ! 626: prevaddressFile = addressFile; ! 627: ! 628: // ! 629: // Reference the next address file on the list, so it ! 630: // stays around. ! 631: // ! 632: ! 633: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 634: ! 635: p = p->Flink; ! 636: while (p != &Address->AddressFileDatabase) { ! 637: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); ! 638: if (addressFile->State != ADDRESSFILE_STATE_OPEN) { ! 639: p = p->Flink; ! 640: continue; ! 641: } ! 642: StReferenceAddressFile(addressFile); ! 643: break; ! 644: } ! 645: ! 646: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 647: ! 648: // ! 649: // Now dereference the previous address file with ! 650: // the lock released. ! 651: // ! 652: ! 653: StDereferenceAddressFile (prevaddressFile); ! 654: ! 655: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 656: ! 657: } // end of loop through the address files. ! 658: ! 659: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 660: ! 661: if (Connection == NULL) { ! 662: ! 663: // ! 664: // We used to return MORE_PROCESSING_REQUIRED, but ! 665: // since we matched with this address, no other ! 666: // address is going to match, so abandon it. ! 667: // ! 668: ! 669: return STATUS_ABANDONED; ! 670: ! 671: } ! 672: ! 673: } else { // end connection == null ! 674: ! 675: UsedListeningConnection = TRUE; ! 676: ! 677: IoAcquireCancelSpinLock (&cancelirql); ! 678: ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql); ! 679: ! 680: p = RemoveHeadList (&Connection->InProgressRequest); ! 681: if (p == &Connection->InProgressRequest) { ! 682: ! 683: Connection->IndicationInProgress = FALSE; ! 684: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 685: IoReleaseCancelSpinLock (cancelirql); ! 686: return STATUS_SUCCESS; ! 687: ! 688: } ! 689: ! 690: // ! 691: // If this listen indicated that we should wait for a ! 692: // TdiAccept, then do that, otherwise the connection is ! 693: // ready. ! 694: // ! 695: ! 696: if ((Connection->Flags2 & CONNECTION_FLAGS2_PRE_ACCEPT) == 0) { ! 697: ! 698: Connection->Flags2 |= CONNECTION_FLAGS2_WAIT_ACCEPT; ! 699: ! 700: } else { ! 701: ! 702: Connection->Flags |= CONNECTION_FLAGS_READY; ! 703: INCREMENT_COUNTER (Connection->Provider, OpenConnections); ! 704: ! 705: Connection->Flags2 |= CONNECTION_FLAGS2_REQ_COMPLETED; ! 706: ! 707: StReferenceConnection("Listen completed", Connection); ! 708: ! 709: } ! 710: ! 711: // ! 712: // We have a completed connection with a queued listen. Complete ! 713: // the listen and let the user do an accept at some time down the ! 714: // road. ! 715: // ! 716: ! 717: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 718: ! 719: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage); ! 720: request->IoRequestPacket->CancelRoutine = (PDRIVER_CANCEL)NULL; ! 721: IoReleaseCancelSpinLock (cancelirql); ! 722: ! 723: irpSp = IoGetCurrentIrpStackLocation (request->IoRequestPacket); ! 724: remoteInformation = ! 725: ((PTDI_REQUEST_KERNEL)(&irpSp->Parameters))->ReturnConnectionInformation; ! 726: if (remoteInformation != NULL) { ! 727: try { ! 728: if (remoteInformation->RemoteAddressLength != 0) { ! 729: ! 730: // ! 731: // Build a temporary TA_NETBIOS_ADDRESS, then ! 732: // copy over as many bytes as fit. ! 733: // ! 734: ! 735: TdiBuildNetbiosAddress( ! 736: Connection->CalledAddress.NetbiosName, ! 737: (BOOLEAN)(Connection->CalledAddress.NetbiosNameType == ! 738: TDI_ADDRESS_NETBIOS_TYPE_GROUP), ! 739: &TempAddress); ! 740: ! 741: if (remoteInformation->RemoteAddressLength >= ! 742: sizeof (TA_NETBIOS_ADDRESS)) { ! 743: ! 744: returnLength = sizeof(TA_NETBIOS_ADDRESS); ! 745: remoteInformation->RemoteAddressLength = returnLength; ! 746: ! 747: } else { ! 748: ! 749: returnLength = remoteInformation->RemoteAddressLength; ! 750: ! 751: } ! 752: ! 753: RtlCopyMemory( ! 754: (PTA_NETBIOS_ADDRESS)remoteInformation->RemoteAddress, ! 755: &TempAddress, ! 756: returnLength); ! 757: ! 758: } else { ! 759: ! 760: returnLength = 0; ! 761: } ! 762: ! 763: status = STATUS_SUCCESS; ! 764: ! 765: } except (EXCEPTION_EXECUTE_HANDLER) { ! 766: ! 767: returnLength = 0; ! 768: status = GetExceptionCode (); ! 769: ! 770: } ! 771: ! 772: } else { ! 773: ! 774: status = STATUS_SUCCESS; ! 775: returnLength = 0; ! 776: ! 777: } ! 778: ! 779: // ! 780: // Don't clear this until now, so that the connection is all ! 781: // set up before we allow more indications. ! 782: // ! 783: ! 784: Connection->IndicationInProgress = FALSE; ! 785: ! 786: StCompleteRequest (request, status, 0); ! 787: ! 788: } ! 789: ! 790: ! 791: // ! 792: // Before we continue, store the remote guy's transport address ! 793: // into the TdiListen's TRANSPORT_CONNECTION buffer. This allows ! 794: // the client to determine who called him. ! 795: // ! 796: ! 797: Connection->CalledAddress.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; ! 798: NdisMoveFromMappedMemory( ! 799: Connection->CalledAddress.NetbiosName, ! 800: Header->Source, ! 801: 16); ! 802: ! 803: NdisMoveFromMappedMemory( ! 804: Connection->RemoteName, ! 805: Header->Source, ! 806: 16); ! 807: ! 808: Connection->Flags2 |= CONNECTION_FLAGS2_REMOTE_VALID; ! 809: ! 810: if (ConnectIndicationBlocked) { ! 811: addressFile->ConnectIndicationInProgress = FALSE; ! 812: } ! 813: ! 814: StDereferenceConnection("ProcessNameQuery done", Connection); ! 815: ! 816: return STATUS_ABANDONED; ! 817: ! 818: } /* StProcessConnect */ ! 819: ! 820: ! 821: NTSTATUS ! 822: StProcessConnectionless( ! 823: IN PDEVICE_CONTEXT DeviceContext, ! 824: IN PHARDWARE_ADDRESS SourceAddress, ! 825: IN PST_HEADER StHeader, ! 826: IN ULONG StLength, ! 827: IN PUCHAR SourceRouting, ! 828: IN UINT SourceRoutingLength, ! 829: OUT PTP_ADDRESS * DatagramAddress ! 830: ) ! 831: ! 832: /*++ ! 833: ! 834: Routine Description: ! 835: ! 836: This routine receives control from the data link provider as an ! 837: indication that a connectionless frame has been received on the data link. ! 838: Here we dispatch to the correct handler. ! 839: ! 840: Arguments: ! 841: ! 842: DeviceContext - Pointer to our device context. ! 843: ! 844: SourceAddress - Pointer to the source hardware address in the received ! 845: frame. ! 846: ! 847: StHeader - Points to the ST header of the incoming packet. ! 848: ! 849: StLength - Actual length in bytes of the packet, starting at the ! 850: StHeader. ! 851: ! 852: SourceRouting - Source routing information in the MAC header. ! 853: ! 854: SourceRoutingLength - The length of SourceRouting. ! 855: ! 856: DatagramAddress - If this function returns STATUS_MORE_PROCESSING_ ! 857: REQUIRED, this will be the address the datagram should be ! 858: indicated to. ! 859: ! 860: Return Value: ! 861: ! 862: NTSTATUS - status of operation. ! 863: ! 864: --*/ ! 865: ! 866: { ! 867: PTP_ADDRESS Address; ! 868: KIRQL oldirql; ! 869: NTSTATUS status; ! 870: PLIST_ENTRY Flink; ! 871: BOOLEAN MatchedAddress; ! 872: PUCHAR MatchName; ! 873: ! 874: // ! 875: // Verify that this frame is long enough to examine. ! 876: // ! 877: ! 878: if (StLength < sizeof(ST_HEADER)) { ! 879: return STATUS_ABANDONED; // frame too small. ! 880: } ! 881: ! 882: // ! 883: // We have a valid connectionless protocol frame that's not a ! 884: // datagram, so deliver it to every address which matches the ! 885: // destination name in the frame. ! 886: // ! 887: ! 888: MatchedAddress = FALSE; ! 889: ! 890: // ! 891: // Search for the address; for broadcast datagrams we ! 892: // search for the special "broadcast" address. ! 893: // ! 894: ! 895: if ((StHeader->Command == ST_CMD_DATAGRAM) && ! 896: (StHeader->Flags & ST_FLAGS_BROADCAST)) { ! 897: ! 898: MatchName = NULL; ! 899: ! 900: } else { ! 901: ! 902: MatchName = StHeader->Destination; ! 903: ! 904: } ! 905: ! 906: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql); ! 907: ! 908: for (Flink = DeviceContext->AddressDatabase.Flink; ! 909: Flink != &DeviceContext->AddressDatabase; ! 910: Flink = Flink->Flink) { ! 911: ! 912: Address = CONTAINING_RECORD ( ! 913: Flink, ! 914: TP_ADDRESS, ! 915: Linkage); ! 916: ! 917: if ((Address->Flags & ADDRESS_FLAGS_STOPPING) != 0) { ! 918: continue; ! 919: } ! 920: ! 921: if (StMatchNetbiosAddress (Address, MatchName)) { ! 922: ! 923: StReferenceAddress ("UI Frame", Address); // prevent address from being destroyed. ! 924: MatchedAddress = TRUE; ! 925: break; ! 926: ! 927: } ! 928: } ! 929: ! 930: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 931: ! 932: if (MatchedAddress) { ! 933: ! 934: // ! 935: // Deliver the frame to the current address. ! 936: // ! 937: ! 938: switch (StHeader->Command) { ! 939: ! 940: case ST_CMD_CONNECT: ! 941: ! 942: status = StProcessConnect ( ! 943: DeviceContext, ! 944: Address, ! 945: StHeader, ! 946: SourceAddress, ! 947: SourceRouting, ! 948: SourceRoutingLength); ! 949: ! 950: break; ! 951: ! 952: case ST_CMD_DATAGRAM: ! 953: ! 954: // ! 955: // Reference the datagram so it sticks around until the ! 956: // ReceiveComplete, when it is processed. ! 957: // ! 958: ! 959: StReferenceAddress ("Datagram indicated", Address); ! 960: *DatagramAddress = Address; ! 961: status = STATUS_MORE_PROCESSING_REQUIRED; ! 962: break; ! 963: ! 964: default: ! 965: ! 966: ASSERT(FALSE); ! 967: ! 968: } /* switch on frame command code */ ! 969: ! 970: StDereferenceAddress ("Done", Address); // done with previous address. ! 971: ! 972: } else { ! 973: ! 974: status = STATUS_ABANDONED; ! 975: ! 976: } ! 977: ! 978: return status; ! 979: ! 980: } /* StProcessConnectionless */ ! 981:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.