Annotation of ntddk/src/network/tdi/uframes.c, revision 1.1.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.