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