|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
ppp.c
Abstract:
This module implements routines that are used for PPP functionality
Author:
Shirish Koti
Revision History: 11 Mar 1998 Initial Version
--*/
#define ARAP_LOCALS
#include <atalk.h>
#pragma hdrstop
#define FILENUM PPP
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE_PPP, AllocPPPConn)
#pragma alloc_text(PAGE_PPP, PPPProcessIoctl)
#pragma alloc_text(PAGE_PPP, PPPRoutePacketToWan)
#pragma alloc_text(PAGE_PPP, PPPTransmit)
#pragma alloc_text(PAGE_PPP, PPPTransmitCompletion)
#pragma alloc_text(PAGE_PPP, DerefPPPConn)
#pragma alloc_text(PAGE_PPP, PPPGetDynamicAddr)
#endif
//***
//
// Function: AllocPPPConn
// Allocate a connection element and initialize fields
//
// Parameters: none
//
// Return: pointer to a newly allocated connection element
//
//***$
PATCPCONN AllocPPPConn( IN VOID ) {
PATCPCONN pAtcpConn; KIRQL OldIrql;
DBG_PPP_CHECK_PAGED_CODE();
if ( (pAtcpConn = AtalkAllocZeroedMemory(sizeof(ATCPCONN))) == NULL) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("AllocPPPConn: alloc failed\n"));
return(NULL); }
#if DBG
pAtcpConn->Signature = ATCPCONN_SIGNATURE; #endif
// RAS refcount
pAtcpConn->RefCount = 1; pAtcpConn->Flags |= ATCP_DLL_SETUP_DONE;
INITIALIZE_SPIN_LOCK(&pAtcpConn->SpinLock);
KeInitializeEvent(&pAtcpConn->NodeAcquireEvent, NotificationEvent, FALSE);
// and insert it in the list
ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql); InsertTailList(&RasPortDesc->pd_PPPConnHead, &pAtcpConn->Linkage); RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql); PPPConnections++; RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
return( pAtcpConn ); }
//***
//
// Function: PPPProcessIoctl
// This routine gets called in to process ioclts coming from ATCP
// For SETUP, we allocate a connection context, get an address for
// the client, get the zone and router info.
// For CLOSE, we mark and dereference our connection context
//
// Parameters: pIrp - irp from ATCP
// pSndRcvInfo - buffer from ATCP that contains all the info
// IoControlCode - what does ATCP want to do
//
// Return: none
//
//***$
NTSTATUS FASTCALL PPPProcessIoctl( IN PIRP pIrp, IN OUT PARAP_SEND_RECV_INFO pSndRcvInfo, IN ULONG IoControlCode, IN PATCPCONN pIncomingAtcpConn ) { KIRQL OldIrql; PATCPINFO pAtcpInfo; PATCPCONN pAtcpConn; DWORD dwRetCode=ARAPERR_NO_ERROR; PATCP_SUPPRESS_INFO pSupprInfo; ATALK_NODEADDR ClientNode; DWORD DataLen=0; DWORD ErrCode; BOOLEAN fDerefPort=FALSE; NTSTATUS ReturnStatus=STATUS_SUCCESS;
DBG_PPP_CHECK_PAGED_CODE();
pAtcpConn = pIncomingAtcpConn;
switch (IoControlCode) { case IOCTL_ATCP_SETUP_CONNECTION:
ErrCode = ATALK_PORT_INVALID;
// put a IrpProcess refcount, so AtalkDefaultPort doesn't go away in PnP
if (!AtalkReferenceDefaultPort()) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPProcessIoctl: Default port gone, or going %lx not accepted (%lx)\n", pIrp,IoControlCode));
dwRetCode = ARAPERR_STACK_IS_NOT_ACTIVE;
break; }
fDerefPort = TRUE;
// allocate connection context
pAtcpConn = AllocPPPConn(); if (!pAtcpConn) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPProcessIoctl: alloc failed\n")); pSndRcvInfo->StatusCode = ARAPERR_OUT_OF_RESOURCES; break; }
pAtcpConn->pDllContext = pSndRcvInfo->pDllContext;
dwRetCode = PPPGetDynamicAddr(pAtcpConn); if (dwRetCode != ARAPERR_NO_ERROR) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPProcessIoctl: couldn't get network addr %ld (%lx)\n", dwRetCode,pAtcpConn));
dwRetCode = ARAPERR_NO_NETWORK_ADDR;
// remove the creation refcount
DerefPPPConn(pAtcpConn); break; }
pAtcpInfo = (PATCPINFO)&pSndRcvInfo->Data[0];
ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
ACQUIRE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
if ((AtalkDefaultPort->pd_Flags & PD_PNP_RECONFIGURE) || (AtalkDefaultPort->pd_Flags & PD_CLOSING)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPProcessIoctl: PnP is ine progress\n"));
dwRetCode = ARAPERR_STACK_IS_NOT_ACTIVE; RELEASE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock); RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
// remove the creation refcount
DerefPPPConn(pAtcpConn); break; }
// we will be returning server's address and router's address
DataLen += (2*sizeof(NET_ADDR));
// copy server's net address
pAtcpInfo->ServerAddr.ata_Network = AtalkDefaultPort->pd_Nodes->an_NodeAddr.atn_Network; pAtcpInfo->ServerAddr.ata_Node = AtalkDefaultPort->pd_Nodes->an_NodeAddr.atn_Node;
// if we are a router, copy our own address
if (AtalkDefaultPort->pd_Flags & PD_ROUTER_RUNNING) { pAtcpInfo->DefaultRouterAddr.ata_Network = AtalkDefaultPort->pd_RouterNode->an_NodeAddr.atn_Network; pAtcpInfo->DefaultRouterAddr.ata_Network = AtalkDefaultPort->pd_RouterNode->an_NodeAddr.atn_Node; }
// if we know who the router on the net is, copy his address
else if (AtalkDefaultPort->pd_Flags & PD_SEEN_ROUTER_RECENTLY) { pAtcpInfo->DefaultRouterAddr.ata_Network = AtalkDefaultPort->pd_ARouter.atn_Network; pAtcpInfo->DefaultRouterAddr.ata_Node = AtalkDefaultPort->pd_ARouter.atn_Node; }
// hmmm: no router!
else { pAtcpInfo->DefaultRouterAddr.ata_Network = 0; pAtcpInfo->DefaultRouterAddr.ata_Node = 0; }
//
// copy the name of the zone on which this server lives
//
if (AtalkDesiredZone) { pAtcpInfo->ServerZoneName[0] = AtalkDesiredZone->zn_ZoneLen; RtlCopyMemory( &pAtcpInfo->ServerZoneName[1], &AtalkDesiredZone->zn_Zone[0], AtalkDesiredZone->zn_ZoneLen ); } else if (AtalkDefaultPort->pd_DefaultZone) { pAtcpInfo->ServerZoneName[0] = AtalkDefaultPort->pd_DefaultZone->zn_ZoneLen; RtlCopyMemory( &pAtcpInfo->ServerZoneName[1], &AtalkDefaultPort->pd_DefaultZone->zn_Zone[0], AtalkDefaultPort->pd_DefaultZone->zn_ZoneLen ); } else { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPProcessIoctl: Server not in any zone!!\n")); pAtcpInfo->ServerZoneName[0] = 0; }
RELEASE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock); RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
DataLen += pAtcpInfo->ServerZoneName[0];
// return our context and the network addr to the dll
pSndRcvInfo->AtalkContext = pAtcpConn;
pSndRcvInfo->ClientAddr.ata_Network = pAtcpConn->NetAddr.atn_Network; pSndRcvInfo->ClientAddr.ata_Node = pAtcpConn->NetAddr.atn_Node;
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPProcessIoctl: PPP conn %lx created, addr = %x.%x\n", pAtcpConn,pSndRcvInfo->ClientAddr.ata_Network,pSndRcvInfo->ClientAddr.ata_Node)); break;
case IOCTL_ATCP_SUPPRESS_BCAST:
pSupprInfo = (PATCP_SUPPRESS_INFO)&pSndRcvInfo->Data[0];
//
// see what flags need to be set: suppress only RTMP only or all bcast
//
ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
if (pSupprInfo->SuppressRtmp) { pAtcpConn->Flags |= ATCP_SUPPRESS_RTMP; }
if (pSupprInfo->SuppressAllBcast) { pAtcpConn->Flags |= ATCP_SUPPRESS_ALLBCAST; }
RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
break;
case IOCTL_ATCP_CLOSE_CONNECTION:
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPProcessIoctl: close connection received on %lx (refcount %d)\n", pAtcpConn,pAtcpConn->RefCount));
ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql); pAtcpConn->Flags &= ~(ATCP_CONNECTION_UP | ATCP_DLL_SETUP_DONE); RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
// PPP wants to close connection: take away the RAS refcount
DerefPPPConn(pAtcpConn);
break;
default: ASSERT(0); break; }
pSndRcvInfo->DataLen = DataLen; pSndRcvInfo->StatusCode = dwRetCode;
// complete that irp
ARAP_COMPLETE_IRP(pIrp, (sizeof(ARAP_SEND_RECV_INFO)+DataLen), STATUS_SUCCESS, &ReturnStatus);
if (fDerefPort) { // remove that IrpProcess refcount
AtalkPortDereference(AtalkDefaultPort); }
return ReturnStatus; }
//***
//
// Function: DerefPPPConn
// Decrements the refcount of the connection element by 1. If the
// refcount goes to 0, releases network addr and frees it
//
// Parameters: pAtcpConn - connection element in question
//
// Return: none
//
//***$
VOID DerefPPPConn( IN PATCPCONN pAtcpConn ) {
KIRQL OldIrql; BOOLEAN fKill = FALSE;
DBG_PPP_CHECK_PAGED_CODE();
ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
ASSERT(pAtcpConn->Signature == ATCPCONN_SIGNATURE);
ASSERT(pAtcpConn->RefCount > 0);
pAtcpConn->RefCount--;
if (pAtcpConn->RefCount == 0) { if (!(pAtcpConn->Flags & ATCP_CONNECTION_CLOSING)) { fKill = TRUE; pAtcpConn->Flags |= ATCP_CONNECTION_CLOSING; } }
RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
if (!fKill) { return; }
// and remove from the list
ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql); RemoveEntryList(&pAtcpConn->Linkage); RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
// free that memory
AtalkFreeMemory(pAtcpConn);
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("DerefPPPConn: PPP connection %lx freed\n",pAtcpConn));
ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql); PPPConnections--; RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
// if possible (i.e. if this was the last connection), unlock PPP pages
AtalkUnlockPPPIfNecessary(); }
//***
//
// Function: FindAndRefPPPConnByAddr
// Finds the corresponding connection element, given the network
// address (of the remote client)
//
// Parameters: destNode - network addr of the destination (remote client)
// pdwFlags - pointer to a dword to return Flags field
//
// Return: pointer to the corresponding connection element, if found
//
//***$
PATCPCONN FindAndRefPPPConnByAddr( IN ATALK_NODEADDR destNode, OUT DWORD *pdwFlags ) { PATCPCONN pAtcpConn=NULL; PATCPCONN pAtcpWalker; PLIST_ENTRY pList; KIRQL OldIrql;
// RAS not configured?
if (!RasPortDesc) { return(NULL); }
ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
if (!(RasPortDesc->pd_Flags & PD_ACTIVE)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("FindAndRefPPPConnByAddr: RAS not active, ignoring\n")); RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql); return(NULL); }
pList = RasPortDesc->pd_PPPConnHead.Flink;
//
// walk through all the PPP clients to see if we find ours
//
while (pList != &RasPortDesc->pd_PPPConnHead) { pAtcpWalker = CONTAINING_RECORD(pList, ATCPCONN, Linkage);
pList = pAtcpWalker->Linkage.Flink;
ACQUIRE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock);
if (ATALK_NODES_EQUAL(&pAtcpWalker->NetAddr, &destNode)) { pAtcpConn = pAtcpWalker; pAtcpConn->RefCount++;
*pdwFlags = pAtcpWalker->Flags;
RELEASE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock); break; }
RELEASE_SPIN_LOCK_DPC(&pAtcpWalker->SpinLock); }
RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
return( pAtcpConn ); }
//***
//
// Function: PPPRoutePacketToWan
// This routine picks up a packet from the lan, checks to see if
// it must be forwarded to any of the PPP clients and does the
// good deed.
//
// Parameters: pDestAddr - who is this packet addressed to? (potentially bcast)
// pSrcAddr - who sent this packet
// Protocol - what packet is it? (ATP, NBP, etc.)
// packet - buffer containing the packet
// PktLen - how big is the packet
// broadcast - is this a broadcast packet?
// pDelivered - set on return: did we forward it to any dial-in
// client (set to TRUE only for directed dgrams)
//
// Return: none
//
//***$
VOID PPPRoutePacketToWan( IN ATALK_ADDR *pDestAddr, IN ATALK_ADDR *pSrcAddr, IN BYTE Protocol, IN PBYTE packet, IN USHORT PktLen, IN USHORT HopCount, IN BOOLEAN broadcast, OUT PBOOLEAN pDelivered ) {
KIRQL OldIrql; PATCPCONN pAtcpConn; PATCPCONN pPrevAtcpConn; PLIST_ENTRY pConnList; ATALK_NODEADDR DestNode; ATALK_NODEADDR SourceNode; DWORD StatusCode; DWORD dwFlags; BOOLEAN fRtmpPacket=FALSE;
DBG_PPP_CHECK_PAGED_CODE();
// assume for now
*pDelivered = FALSE;
//
// if this is a unicast, see if a PPP client with this dest address exists
//
if (!broadcast) {
DestNode.atn_Network = pDestAddr->ata_Network; DestNode.atn_Node = pDestAddr->ata_Node;
// first and foremost, let's find the puppy
pAtcpConn = FindAndRefPPPConnByAddr(DestNode, &dwFlags);
if (pAtcpConn == NULL) { return; }
// let the caller know that we found who this data was meant for
*pDelivered = TRUE;
// if this dude isn't ready to route data, drop this packet!
if (!(dwFlags & ATCP_CONNECTION_UP)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN, ("PPPRoutePacketToWan: dropping pkt on %lx, line-up not done\n",pAtcpConn));
// remove the refcount put in by FindAndRefPPPConnByAddr
DerefPPPConn(pAtcpConn);
return; }
// send the packet out
PPPTransmit(pAtcpConn, pDestAddr, pSrcAddr, Protocol, packet, PktLen, HopCount);
// remove the refcount put in by FindAndRefPPPConnByAddr
DerefPPPConn(pAtcpConn);
return; }
//
// it's a broadcast packet: must send it to all the PPP guys
//
if (packet[LDDP_PROTO_TYPE_OFFSET] == DDPPROTO_RTMPRESPONSEORDATA) { fRtmpPacket = TRUE; }
pAtcpConn = NULL; pPrevAtcpConn = NULL;
SourceNode.atn_Network = pSrcAddr->ata_Network; SourceNode.atn_Node = pSrcAddr->ata_Node;
while (1) { ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
//
// first, let's find the right connection to work on
//
while (1) { // if we're in the middle of the list, get to the next guy
if (pAtcpConn != NULL) { pConnList = pAtcpConn->Linkage.Flink; } // we're just starting: get the guy at the head of the list
else { pConnList = RasPortDesc->pd_PPPConnHead.Flink; }
// finished all?
if (pConnList == &RasPortDesc->pd_PPPConnHead) { RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
if (pPrevAtcpConn) { DerefPPPConn(pPrevAtcpConn); } return; }
pAtcpConn = CONTAINING_RECORD(pConnList, ATCPCONN, Linkage);
ACQUIRE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
// if this guy sent out the broadcast, don't send it back to him!
if (ATALK_NODES_EQUAL(&pAtcpConn->NetAddr, &SourceNode)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN, ("PPPRoutePacketToWan: skipping bcast from source\n")); RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock); continue; }
// if this dude isn't ready to route data, skip
if (!(pAtcpConn->Flags & ATCP_CONNECTION_UP)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN, ("PPPRoutePacketToWan: skipping %lx because line-up not done\n",pAtcpConn)); RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock); continue; }
//
// if this is an RTMP packet and the client doesn't want those
// packets, don't send
//
if (fRtmpPacket && (pAtcpConn->Flags & ATCP_SUPPRESS_RTMP)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN, ("PPPRoutePacketToWan: skipping %lx because RTMP data to be suppressed\n",pAtcpConn)); RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock); continue; }
// if this dude wants all broadcasts suppressed, skip it
if (pAtcpConn->Flags & ATCP_SUPPRESS_ALLBCAST) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_WARN, ("PPPRoutePacketToWan: skipping %lx because all bcast to be suppressed\n",pAtcpConn)); RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock); continue; }
// let's make sure this connection stays around till we finish
pAtcpConn->RefCount++;
RELEASE_SPIN_LOCK_DPC(&pAtcpConn->SpinLock);
break; }
RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
//
// remove the refcount on the previous connection we put in earlier
//
if (pPrevAtcpConn) { DerefPPPConn(pPrevAtcpConn); }
ASSERT(pPrevAtcpConn != pAtcpConn);
pPrevAtcpConn = pAtcpConn;
PPPTransmit(pAtcpConn, pDestAddr, pSrcAddr, Protocol, packet, PktLen, HopCount); }
}
//***
//
// Function: PPPTransmit
// This routine sends the packet out to a PPP destination
//
// Parameters: pAtcpConn - PPP connection to send to
// pDestAddr - who is this packet addressed to? (potentially bcast)
// pSrcAddr - who sent this packet
// Protocol - what packet is it? (ATP, NBP, etc.)
// packet - buffer containing the packet
// PktLen - how big is the packet
// HopCount - hopcount in the DDP pkt as received
//
// Return: none
//
//***$
VOID FASTCALL PPPTransmit( IN PATCPCONN pAtcpConn, IN ATALK_ADDR *pDestAddr, IN ATALK_ADDR *pSrcAddr, IN BYTE Protocol, IN PBYTE packet, IN USHORT PktLen, IN USHORT HopCount ) {
PBUFFER_DESC pBufCopy; PBUFFER_DESC pPktDesc; SEND_COMPL_INFO SendInfo; PBYTE pLinkDdpOptHdr; PBYTE pDgram; ATALK_ERROR error;
DBG_PPP_CHECK_PAGED_CODE();
// allocate a buffer and bufdesc to copy the incoming packet (data portion)
pBufCopy = AtalkAllocBuffDesc(NULL,PktLen,(BD_FREE_BUFFER | BD_CHAR_BUFFER));
if (pBufCopy == NULL) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPTransmit: alloc BufDesc failed\n")); return; }
// copy the data in
AtalkCopyBufferToBuffDesc(packet, PktLen, pBufCopy, 0);
// allocate a buffdesc to hold headers
AtalkNdisAllocBuf(&pPktDesc); if (pPktDesc == NULL) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPTransmit: couldn't alloc ndis bufdesc\n"));
AtalkFreeBuffDesc(pBufCopy); return; }
// put in the Mac header (NdisWan's header)
pLinkDdpOptHdr = pPktDesc->bd_CharBuffer;
AtalkNdisBuildPPPPHdr(pLinkDdpOptHdr, pAtcpConn);
// make up the DDP header
pDgram = pLinkDdpOptHdr + WAN_LINKHDR_LEN;
*pDgram++ = (DDP_HOP_COUNT(HopCount) + DDP_MSB_LEN(PktLen + LDDP_HDR_LEN)); PUTSHORT2BYTE(pDgram, (PktLen + LDDP_HDR_LEN)); pDgram++; PUTSHORT2SHORT(pDgram, 0); pDgram += sizeof(USHORT); PUTSHORT2SHORT(pDgram, pDestAddr->ata_Network); pDgram += sizeof(USHORT); PUTSHORT2SHORT(pDgram, pSrcAddr->ata_Network); pDgram += sizeof(USHORT); *pDgram++ = pDestAddr->ata_Node; *pDgram++ = pSrcAddr->ata_Node; *pDgram++ = pDestAddr->ata_Socket; *pDgram++ = pSrcAddr->ata_Socket; *pDgram++ = Protocol; // Set length in the buffer descriptor.
AtalkSetSizeOfBuffDescData(pPktDesc, WAN_LINKHDR_LEN + LDDP_HDR_LEN);
// chain in this bufdesc
AtalkPrependBuffDesc(pPktDesc, pBufCopy);
INTERLOCKED_ADD_STATISTICS(&RasPortDesc->pd_PortStats.prtst_DataOut, AtalkSizeBuffDesc(pPktDesc), &AtalkStatsLock.SpinLock);
// set up our completion info
SendInfo.sc_TransmitCompletion = PPPTransmitCompletion; SendInfo.sc_Ctx1 = RasPortDesc; SendInfo.sc_Ctx2 = pBufCopy; SendInfo.sc_Ctx3 = pAtcpConn;
// send the packet
error = AtalkNdisSendPacket(RasPortDesc, pPktDesc, AtalkDdpSendComplete, &SendInfo); if (!ATALK_SUCCESS(error)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPTransmit: AtalkNdisSendPacket failed %ld\n",error));
AtalkDdpSendComplete(NDIS_STATUS_FAILURE, pPktDesc, &SendInfo); }
}
//***
//
// Function: PPPTransmitCompletion
// This is the completion routine for PPPTransmit, and is called
// by NDIS after the packet is sent out (or failure occurs)
//
// Parameters: Status - how did the send go
// pSendInfo - completion info
//
// Return: none
//
//***$
VOID FASTCALL PPPTransmitCompletion( IN NDIS_STATUS Status, IN PSEND_COMPL_INFO pSendInfo ) { PBUFFER_DESC pBuffDesc;
DBG_PPP_CHECK_PAGED_CODE();
pBuffDesc = (PBUFFER_DESC)(pSendInfo->sc_Ctx2);
ASSERT(pBuffDesc != NULL); ASSERT(pBuffDesc->bd_Flags & (BD_CHAR_BUFFER | BD_FREE_BUFFER));
if (Status != 0) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("PPPTransmitCompletion: send failed, %lx on %lx\n", Status,pSendInfo->sc_Ctx3)); }
AtalkFreeBuffDesc(pBuffDesc); }
//***
//
// Function: PPPGetDynamicAddr
// This routine gets a network address for a PPP dial-in client.
// It does the same AARP logic as if it were acquiring a
// node-address for the host itself.
//
// Parameters: pAtcpConn - the connection for which we need a network addr
//
// Return: ARAPERR_NO_ERROR if all went well.
//
//***$
DWORD PPPGetDynamicAddr( IN PATCPCONN pAtcpConn ) { ATALK_NODEADDR NetAddr; ATALK_NETWORKRANGE NetRange; BOOLEAN fFound=FALSE; KIRQL OldIrql; DWORD StatusCode=ARAPERR_STACK_NOT_UP;
DBG_PPP_CHECK_PAGED_CODE();
ASSERT(AtalkDefaultPort != NULL);
//
// go find a node address on the default port (we'll never get this far if
// default port isn't up yet)
//
ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
ASSERT(!(pAtcpConn->Flags & ATCP_FINDING_NODE));
pAtcpConn->Flags |= ATCP_FINDING_NODE;
RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
AtalkLockInitIfNecessary();
// if we are stuck in the startup range, use that range for dial-in guys, too
if (WITHIN_NETWORK_RANGE(AtalkDefaultPort->pd_NetworkRange.anr_LastNetwork, &AtalkStartupNetworkRange)) { NetRange = AtalkStartupNetworkRange; } else { NetRange = AtalkDefaultPort->pd_NetworkRange; } fFound = AtalkInitAarpForNodeInRange(AtalkDefaultPort, (PVOID)pAtcpConn, TRUE, NetRange, &NetAddr);
AtalkUnlockInitIfNecessary();
ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
pAtcpConn->Flags &= ~ATCP_FINDING_NODE;
if (fFound) { // store that adddr!
pAtcpConn->NetAddr.atn_Network = NetAddr.atn_Network; pAtcpConn->NetAddr.atn_Node = NetAddr.atn_Node;
pAtcpConn->Flags |= ATCP_NODE_IN_USE; StatusCode = ARAPERR_NO_ERROR;
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO, ("PPPGetDynamicAddr: found addr for PPP client = %lx %lx\n", NetAddr.atn_Network,NetAddr.atn_Node)); } else { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("ArapGetDynamicAddr: PPP: no more network addr left?\n"));
pAtcpConn->Flags &= ~ATCP_NODE_IN_USE; pAtcpConn->NetAddr.atn_Network = 0; pAtcpConn->NetAddr.atn_Node = 0; StatusCode = ARAPERR_NO_NETWORK_ADDR; }
RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
return(StatusCode); }
|