Annotation of ntddk/src/network/tdi/uframes.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.