windows-nt/Source/XPSP1/NT/net/rras/ras/ppp/rasatcp/rasatcp.c
2020-09-26 16:20:57 +08:00

1050 lines
28 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************/
/** Copyright(c) 1998 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: rasatcp.c
//
// Description: Contains routines that implement the ATCP functionality.
//
// History: Feb 26, 1998 Shirish Koti Created original version.
//
//***
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <lmcons.h>
#include <string.h>
#include <stdlib.h>
#include <llinfo.h>
#include <rasman.h>
#include <rtutils.h>
#include <devioctl.h>
#include <rasppp.h>
#include <pppcp.h>
#define INCL_HOSTWIRE
#include <ppputil.h>
#include <raserror.h>
#include <arapio.h>
#include "rasatcp.h"
//
// Globals
//
HANDLE AtcpHandle=NULL;
CRITICAL_SECTION AtcpCritSect;
NET_ADDR AtcpServerAddress;
NET_ADDR AtcpDefaultRouter;
DWORD AtcpNumConnections=0;
UCHAR AtcpServerName[NAMESTR_LEN];
UCHAR AtcpZoneName[ZONESTR_LEN];
//***
//
// Function: atcpStartup
// This routine does init time setup
//
// Return: result of operation
//
//***$
DWORD
atcpStartup(
IN VOID
)
{
DWORD dwRetCode=NO_ERROR;
DWORD dwSrvNameLen=MAX_COMPUTERNAME_LENGTH+1;
// get the server name
if (!GetComputerName((LPTSTR)&AtcpServerName[1],&dwSrvNameLen))
{
dwRetCode = GetLastError();
ATCP_DBGPRINT(("atcpStartup: GetComputerName failed %ld\n",dwRetCode));
return(dwRetCode);
}
// store it in Pascal string format
AtcpServerName[0] = (BYTE)dwSrvNameLen;
InitializeCriticalSection( &AtcpCritSect );
return(dwRetCode);
}
//***
//
// Function: atcpOpenHandle
// Opens the RAS device exported by the appletalk stack
//
// Parameters: None
//
// Return: None
//
// Globals: AtcpHandle, if successful
//
//***$
VOID
atcpOpenHandle(
IN VOID
)
{
NTSTATUS status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING DeviceName;
IO_STATUS_BLOCK IoStatus;
HANDLE hLocalHandle;
if (AtcpHandle)
{
ATCP_DBGPRINT(("atcpOpenHandle: handle %lx already open!\n",AtcpHandle));
return;
}
RtlInitUnicodeString( &DeviceName, ARAP_DEVICE_NAME );
InitializeObjectAttributes(
&ObjectAttributes,
&DeviceName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = NtCreateFile(
&hLocalHandle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&ObjectAttributes,
&IoStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
0,
NULL,
0 );
if ( NT_SUCCESS(status) )
{
AtcpHandle = hLocalHandle;
ATCP_DBGPRINT(("atcpOpenHandle: NtCreateFile succeeded\n",status));
}
else
{
ATCP_DBGPRINT(("atcpOpenHandle: NtCreateFile failed %lx\n",status));
}
}
//***
//
// Function: atcpCloseHandle
// Closes the RAS device (opened in atcpOpenHandle)
//
// Parameters: None
//
// Return: None
//
// Globals: AtalkHandle
//
//***$
VOID
atcpCloseHandle(
IN VOID
)
{
NTSTATUS status=STATUS_SUCCESS;
if (!AtcpHandle)
{
ATCP_DBGPRINT(("atcpCloseHandle: handle already closed!\n"));
return;
}
status = NtClose( AtcpHandle );
AtcpHandle = NULL;
if ( !NT_SUCCESS( status ) )
{
ATCP_DBGPRINT(("atcpCloseHandle: NtClose failed %lx\n",status));
ATCP_ASSERT(0);
}
else
{
ATCP_DBGPRINT(("atcpCloseHandle: NtClose succeeded\n",status));
}
}
//***
//
// Function: atcpAtkSetup
// This is the entry point into the stack to tell the stack to
// set up a context for this connection, to get a network address
// for the dial-in client, server's zone name, and router address
//
// Parameters: pAtcpConn - connection context
//
// Return: status returned by NtDeviceIoControlFile
//
//***$
DWORD
atcpAtkSetup(
IN PATCPCONN pAtcpConn,
IN ULONG IoControlCode
)
{
NTSTATUS status;
IO_STATUS_BLOCK iosb;
HANDLE Event;
BYTE Buffer[sizeof(ARAP_SEND_RECV_INFO) + sizeof(ATCPINFO)];
PARAP_SEND_RECV_INFO pSndRcvInfo;
PATCPINFO pAtcpInfo;
PATCP_SUPPRESS_INFO pSupprInfo;
DWORD dwRetCode=NO_ERROR;
RtlZeroMemory((PBYTE)Buffer, sizeof(Buffer));
pSndRcvInfo = (PARAP_SEND_RECV_INFO)Buffer;
pSndRcvInfo->StatusCode = (DWORD)-1;
pSndRcvInfo->pDllContext = (PVOID)pAtcpConn;
pSndRcvInfo->IoctlCode = IoControlCode;
pSndRcvInfo->ClientAddr = pAtcpConn->ClientAddr;
if (IoControlCode == IOCTL_ATCP_SETUP_CONNECTION)
{
pSndRcvInfo->DataLen = sizeof(ATCPINFO);
}
else if (IoControlCode == IOCTL_ATCP_SUPPRESS_BCAST)
{
// if we don't need to suppress broadcasts, done here
if ((!pAtcpConn->SuppressRtmp) && (!pAtcpConn->SuppressAllBcast))
{
return(NO_ERROR);
}
pSndRcvInfo->DataLen = sizeof(ATCP_SUPPRESS_INFO);
pSupprInfo = (PATCP_SUPPRESS_INFO)&pSndRcvInfo->Data[0];
pSupprInfo->SuppressRtmp = pAtcpConn->SuppressRtmp;
pSupprInfo->SuppressAllBcast = pAtcpConn->SuppressAllBcast;
}
else
{
pSndRcvInfo->DataLen = 0;
}
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (Event == NULL)
{
ATCP_DBGPRINT(("atcpAtkSetup: CreateEvent failed (%ld)\n",GetLastError()));
return(ARAPERR_OUT_OF_RESOURCES);
}
status = NtDeviceIoControlFile(
AtcpHandle,
Event, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&iosb, // IoStatusBlock
IoControlCode, // IoControlCode
Buffer, // InputBuffer
sizeof(Buffer), // InputBufferSize
Buffer, // OutputBuffer
sizeof(Buffer)); // OutputBufferSize
if (status == STATUS_PENDING)
{
status = NtWaitForSingleObject(
Event, // Handle
TRUE, // Alertable
NULL); // Timeout
if (NT_SUCCESS(status))
{
status = iosb.Status;
}
}
if (status != STATUS_SUCCESS)
{
ATCP_DBGPRINT(("atcpAtkSetup: NtDeviceIoControlFile failure (%lx)\n",
status));
dwRetCode = ARAPERR_IOCTL_FAILURE;
}
CloseHandle(Event);
dwRetCode = pSndRcvInfo->StatusCode;
if (dwRetCode != NO_ERROR)
{
ATCP_DBGPRINT(("atcpAtkSetup: ioctl %lx failed %ld\n",
IoControlCode,dwRetCode));
return(dwRetCode);
}
//
// for SETUP ioctl, we have some info from stack we need to copy
//
if (IoControlCode == IOCTL_ATCP_SETUP_CONNECTION)
{
pAtcpInfo = (PATCPINFO)&pSndRcvInfo->Data[0];
// get the client's address out
EnterCriticalSection(&pAtcpConn->CritSect);
pAtcpConn->AtalkContext = pSndRcvInfo->AtalkContext;
pAtcpConn->ClientAddr = pSndRcvInfo->ClientAddr;
LeaveCriticalSection(&pAtcpConn->CritSect);
//
// get the default router's address and the zone name
//
EnterCriticalSection( &AtcpCritSect );
AtcpServerAddress = pAtcpInfo->ServerAddr;
AtcpDefaultRouter = pAtcpInfo->DefaultRouterAddr;
ATCP_ASSERT(pAtcpInfo->ServerZoneName[0] < ZONESTR_LEN);
CopyMemory(&AtcpZoneName[1],
&pAtcpInfo->ServerZoneName[1],
pAtcpInfo->ServerZoneName[0]);
AtcpZoneName[0] = pAtcpInfo->ServerZoneName[0];
// got one more connection!
AtcpNumConnections++;
LeaveCriticalSection( &AtcpCritSect );
}
return(dwRetCode);
}
//***
//
// Function: atcpAllocConnection
// This routine allocates an ATCP connection block, initializes
// it with info provided by PPP engine.
//
// Parameters: pInfo - PPPCP_INIT info
//
// Return: pointer to ATCP connection if successful, NULL otherwise
//
//***$
PATCPCONN
atcpAllocConnection(
IN PPPCP_INIT *pPppInit
)
{
PATCPCONN pAtcpConn=NULL;
pAtcpConn = (PATCPCONN)LocalAlloc(LPTR, sizeof(ATCPCONN));
if (pAtcpConn == NULL)
{
ATCP_DBGPRINT(("atcpAllocConnection: malloc failed\n"));
return(NULL);
}
memset( pAtcpConn, 0, sizeof(ATCPCONN) );
pAtcpConn->Signature = ATCP_SIGNATURE;
// by default, broadcasts are not suppressed
pAtcpConn->SuppressRtmp = FALSE;
pAtcpConn->SuppressAllBcast = FALSE;
pAtcpConn->fLineUpDone = FALSE;
InitializeCriticalSection( &pAtcpConn->CritSect );
pAtcpConn->hPort = pPppInit->hPort;
pAtcpConn->hConnection = pPppInit->hConnection;
return(pAtcpConn);
}
//***
//
// Function: atcpParseRequest
// This routine parses the incoming ATCP packet and prepares a
// response as appropriate (Rej, Nak or Ack)
//
// AppleTalk-Address
// 1 6 0 AT-NET(2) AT-Node (1)
// Routing-Protocol
// 2 4 0 0 (Routing protocol - last 2 bytes - can be 0, 1, 2, 3:
// we only support 0)
// Suppress-Broadcasts
// 3 2 (to suppress all broadcasts)
// 3 3 1 (to suppress RTMP bcasts. We don't support other types)
// AT-Compression-Protocol
// 4 4 Undefined!
// Server-information
// 6 Len .....
// Zone-Information
// 7 Len ZoneName
// Default-Router-Address
// 8 6 0 AT-NET(2) AT-Node (1)
//
//
// Parameters: pAtcpConn - the connection
// pReceiveBuf - PPP_CONFIG info: the request
// pSendBuf - PPP_CONFIG info: our response
// cbSendBuf - how big is the Data buffer for our response (for Rej)
// ParseResult - array where we mark off options we saw
// pfRejectingSomething - pointer to TRUE if Rejecting something
//
// Return: result of the operation
//
//***$
DWORD
atcpParseRequest(
IN PATCPCONN pAtcpConn,
IN PPP_CONFIG *pReceiveBuf,
OUT PPP_CONFIG *pSendBuf,
IN DWORD cbSendBuf,
OUT BYTE ParseResult[ATCP_OPT_MAX_VAL+1],
OUT BOOL *pfRejectingSomething
)
{
PPP_OPTION UNALIGNED *pRequest;
PPP_OPTION UNALIGNED *pReject;
DWORD BytesLeftInSendBuf;
PBYTE pOptData;
USHORT OptDataLen;
USHORT PktLen;
USHORT RequestLen;
USHORT UnParsedBytes;
NET_ADDR ClientAddr;
DWORD i;
*pfRejectingSomething = FALSE;
pRequest = (PPP_OPTION UNALIGNED* )pReceiveBuf->Data;
pReject = (PPP_OPTION UNALIGNED* )pSendBuf->Data;
BytesLeftInSendBuf = cbSendBuf;
PktLen = WireToHostFormat16( pReceiveBuf->Length );
UnParsedBytes = PktLen - PPP_CONFIG_HDR_LEN;
// initialize for now to "nothing requested"
for (i=0; i<ATCP_OPT_MAX_VAL; i++)
{
ParseResult[i] = ATCP_NOT_REQUESTED;
}
//
// we loop until we have parsed all the bytes
//
while (UnParsedBytes > 0)
{
RequestLen = (USHORT)pRequest->Length;
if (UnParsedBytes < RequestLen)
{
ATCP_DBGPRINT(("atcpParseRequest: too few bytes %d vs. %d\n",
UnParsedBytes,RequestLen));
return(ERROR_PPP_INVALID_PACKET);
}
//
// assume we're going to accept this option. We'll overwrite if that's
// not the case
//
ParseResult[pRequest->Type] = ATCP_ACK;
// the point where the data portion for this option starts
pOptData = &pRequest->Data[0];
// remove the Type and Len bytes, remaining is option data
OptDataLen = RequestLen - 2;
#if 0
ATCP_DBGPRINT(("atcpParseRequest: type %d OptLen %d (",
pRequest->Type,OptDataLen));
for (i=0; i<OptDataLen; i++)
{
DbgPrint(" 0x%x",pOptData[i]);
}
DbgPrint(" )\n");
#endif
//
// now look at each of the options and see if we should reject it,
// modify it or accept it (Rej, Nak or Ack)
//
switch (pRequest->Type)
{
//
// client wants an appletalk address. We don't allow the client to
// request which address he wants.
//
case ATCP_OPT_APPLETALK_ADDRESS:
if (RequestLen != 6)
{
ATCP_DBGPRINT(("atcpParseRequest: AT_ADDR wrong pktlen %d\n",
RequestLen));
return(ERROR_PPP_INVALID_PACKET);
}
ClientAddr.ata_Network =
WireToHostFormat16(&pOptData[1]);
ClientAddr.ata_Node = (USHORT)pOptData[3];
if ((ClientAddr.ata_Network == 0) ||
(ClientAddr.ata_Node == 0) ||
(ClientAddr.ata_Network != pAtcpConn->ClientAddr.ata_Network) ||
(ClientAddr.ata_Node != pAtcpConn->ClientAddr.ata_Node))
{
ParseResult[pRequest->Type] = ATCP_NAK;
}
break;
//
// client wants some routing protocol. we don't send out Routing
// info, so we should just Nak this option (unless the client also
// is telling us not to send any routing info)
//
case ATCP_OPT_ROUTING_PROTOCOL:
if (RequestLen < 4)
{
ATCP_DBGPRINT(("atcpParseRequest: ROUTING wrong pktlen %d\n",
RequestLen));
return(ERROR_PPP_INVALID_PACKET);
}
//
// we don't send out Routing info, so attempt to negotiate any
// other protocol should be Nak'ed
//
if ((*(USHORT *)&pOptData[0]) != ATCP_OPT_ROUTING_NONE)
{
ParseResult[pRequest->Type] = ATCP_NAK;
}
break;
//
// client wants to suppress broadcasts of some (or all) types of
// DDP types.
//
case ATCP_OPT_SUPPRESS_BROADCAST:
//
// client wants us to suppress only some bcasts?
//
if (OptDataLen > 0)
{
// if requesting RTMP data suppression, we'll allow it
if (pOptData[0] == DDPPROTO_RTMPRESPONSEORDATA)
{
pAtcpConn->SuppressRtmp = TRUE;
}
// hmm, some other protocol: sorry, no can do
else
{
ATCP_DBGPRINT(("atcpParseRequest: Naking suppression %d\n",
pOptData[0]));
ParseResult[pRequest->Type] = ATCP_NAK;
}
}
else
{
pAtcpConn->SuppressAllBcast = TRUE;
}
break;
//
// client wants to negotiate some compression. No compression
// scheme is defined, so we just have to reject this option
//
case ATCP_OPT_AT_COMPRESSION_PROTOCOL:
ATCP_DBGPRINT(("atcpParseRequest: COMPRESSION sending Rej\n"));
if (BytesLeftInSendBuf >= RequestLen)
{
CopyMemory((PVOID)pReject, (PVOID)pRequest, RequestLen);
BytesLeftInSendBuf -= RequestLen;
}
else
{
ATCP_DBGPRINT(("atcpParseRequest: PPP engine's buffer too small\n",
RequestLen));
return(ERROR_BUFFER_TOO_SMALL);
}
pReject = (PPP_OPTION UNALIGNED *)((BYTE* )pReject + RequestLen);
*pfRejectingSomething = TRUE;
ParseResult[pRequest->Type] = ATCP_REJ;
break;
//
// for the following options, we just take note of the fact that
// the client has requested it and we send the info over. Nothing
// to negotiate in these options.
// (We aren't supposed to Nak these either)
//
case ATCP_OPT_RESERVED:
case ATCP_OPT_SERVER_INFORMATION:
case ATCP_OPT_ZONE_INFORMATION:
case ATCP_OPT_DEFAULT_ROUTER_ADDRESS:
break;
default:
ATCP_DBGPRINT(("atcpParseRequest: unknown type %d\n",
pRequest->Type));
return(ERROR_PPP_INVALID_PACKET);
}
//
// move to the next option
//
UnParsedBytes -= RequestLen;
pRequest = (PPP_OPTION UNALIGNED *)((BYTE* )pRequest + RequestLen);
}
//
// see if we are rejecting some option. If so, set some values
//
if (*pfRejectingSomething)
{
pSendBuf->Code = CONFIG_REJ;
HostToWireFormat16( (USHORT)((PBYTE)pReject - (PBYTE)pSendBuf),
pSendBuf->Length );
ATCP_DUMP_BYTES("atcpParseRequest: Rejecting these options:",
&pSendBuf->Data[0],
(DWORD)WireToHostFormat16( pSendBuf->Length)-4);
}
return(NO_ERROR);
}
//***
//
// Function: atcpPrepareResponse
// This routine prepares a response, depending on what all info
// was parsed out from the client's request.
//
// Parameters: pAtcpConn - the connection
// pSendBuf - PPP_CONFIG info: our response
// cbSendBuf - how big is the Data buffer for our response
// ParseResult - array where we have the parsed info
//
// Return: result of the operation
//
//***$
DWORD
atcpPrepareResponse(
IN PATCPCONN pAtcpConn,
OUT PPP_CONFIG *pSendBuf,
IN DWORD cbSendBuf,
OUT BYTE ParseResult[ATCP_OPT_MAX_VAL+1]
)
{
DWORD dwRetCode=NO_ERROR;
DWORD BytesLeftInSendBuf;
PPP_OPTION UNALIGNED *pResponse;
PBYTE pOptData;
USHORT OptDataLen;
USHORT OptionType;
DWORD i;
BOOL fNakingSomething=FALSE;
BOOL fRequestingSomething=FALSE;
BOOL fIncludeThisOption;
pResponse = (PPP_OPTION UNALIGNED* )pSendBuf->Data;
BytesLeftInSendBuf = cbSendBuf;
// first find out if we are going to be Nak'ing anything
for (OptionType=1; OptionType<ATCP_OPT_MAX_VAL; OptionType++ )
{
if (ParseResult[OptionType] == ATCP_NAK)
{
fNakingSomething = TRUE;
}
}
//
// go through our array to see which options we must send Nak to
// (or construct Ack for the whole request)
//
for (OptionType=1; OptionType<ATCP_OPT_MAX_VAL; OptionType++ )
{
//
// if this option is not (to be) requested, we don't send anything
//
if (ParseResult[OptionType] == ATCP_NOT_REQUESTED)
{
continue;
}
// if Nak'ing something and it's not this option to be Nak'ed, skip it
if (fNakingSomething && (ParseResult[OptionType] != ATCP_NAK))
{
continue;
}
//
// make sure we have at least 2 bytes for the OptionType and OptionLen
//
if (BytesLeftInSendBuf < 2)
{
ATCP_DBGPRINT(("atcpPrepareResponse: A: buf too small\n"));
return(ERROR_BUFFER_TOO_SMALL);
}
BytesLeftInSendBuf -= 2;
pOptData = &pResponse->Data[0];
OptDataLen = 0;
fIncludeThisOption = TRUE;
switch (OptionType)
{
//
// tell client (again) the client's network address
//
case ATCP_OPT_APPLETALK_ADDRESS:
OptDataLen = sizeof(NET_ADDR);
if (BytesLeftInSendBuf < OptDataLen)
{
ATCP_DBGPRINT(("atcpPrepareResponse: B: buf too small\n"));
return(ERROR_BUFFER_TOO_SMALL);
}
// skip the reserved byte
*pOptData++ = 0;
//
// if we are sending our REQUEST, send server's address
//
if (ParseResult[OptionType] == ATCP_REQ)
{
// put in the network address
HostToWireFormat16(AtcpServerAddress.ata_Network, pOptData);
pOptData += sizeof(USHORT);
// put in the network node
ATCP_ASSERT(pAtcpConn->ClientAddr.ata_Node != 0);
*pOptData++ = (BYTE)AtcpServerAddress.ata_Node;
fRequestingSomething = TRUE;
}
//
// no, we must send the client's network address
//
else
{
// put in the network address
HostToWireFormat16(pAtcpConn->ClientAddr.ata_Network, pOptData);
pOptData += sizeof(USHORT);
// put in the network node
ATCP_ASSERT(pAtcpConn->ClientAddr.ata_Node != 0);
*pOptData++ = (BYTE)pAtcpConn->ClientAddr.ata_Node;
}
break;
//
// tell client (again) that we support no routing info
//
case ATCP_OPT_ROUTING_PROTOCOL:
OptDataLen = sizeof(USHORT);
HostToWireFormat16(ATCP_OPT_ROUTING_NONE, pOptData);
pOptData += sizeof(USHORT);
break;
//
// tell client that we can suppress RTMP or all Bcast
//
case ATCP_OPT_SUPPRESS_BROADCAST:
// if this is an ack, see if we have agreed to suppressing RTMP
if (!fNakingSomething)
{
if (pAtcpConn->SuppressRtmp)
{
OptDataLen = 1;
*pOptData++ = DDPPROTO_RTMPRESPONSEORDATA;
}
}
break;
//
// we reach here only if are Acking the client's entire request
//
case ATCP_OPT_SERVER_INFORMATION:
ATCP_ASSERT(ParseResult[OptionType] != ATCP_NAK);
ATCP_ASSERT(!fNakingSomething);
OptDataLen = sizeof(USHORT) + sizeof(DWORD) + AtcpServerName[0];
if (BytesLeftInSendBuf < OptDataLen)
{
ATCP_DBGPRINT(("atcpPrepareResponse: C: buf too small\n"));
return(ERROR_BUFFER_TOO_SMALL);
}
// copy the server's class-id
HostToWireFormat16(ATCP_SERVER_CLASS, pOptData);
pOptData += sizeof(USHORT);
// copy the server's implementation-id
HostToWireFormat32(ATCP_SERVER_IMPLEMENTATION_ID, pOptData);
pOptData += sizeof(DWORD);
// copy the server's name
CopyMemory(pOptData, &AtcpServerName[1], AtcpServerName[0]);
break;
//
// we reach here only if are Acking the client's entire request
//
case ATCP_OPT_ZONE_INFORMATION:
ATCP_ASSERT(ParseResult[OptionType] != ATCP_NAK);
ATCP_ASSERT(!fNakingSomething);
// if we don't have a zone name, skip this option
if (AtcpZoneName[0] == 0)
{
fIncludeThisOption = FALSE;
break;
}
OptDataLen = AtcpZoneName[0];
if (BytesLeftInSendBuf < OptDataLen)
{
ATCP_DBGPRINT(("atcpPrepareResponse: D: buf too small\n"));
return(ERROR_BUFFER_TOO_SMALL);
}
// copy the zone name
CopyMemory(pOptData, &AtcpZoneName[1], AtcpZoneName[0]);
break;
//
// we reach here only if are Acking the client's entire request
//
case ATCP_OPT_DEFAULT_ROUTER_ADDRESS:
ATCP_ASSERT(ParseResult[OptionType] != ATCP_NAK);
ATCP_ASSERT(!fNakingSomething);
// if we don't have a router address, skip this option
if (AtcpDefaultRouter.ata_Network == 0)
{
fIncludeThisOption = FALSE;
break;
}
OptDataLen = sizeof(NET_ADDR);
if (BytesLeftInSendBuf < OptDataLen)
{
ATCP_DBGPRINT(("atcpPrepareResponse: E: buf too small\n"));
return(ERROR_BUFFER_TOO_SMALL);
}
// skip the reserved byte
*pOptData++ = 0;
// put in the network address
HostToWireFormat16(AtcpDefaultRouter.ata_Network, pOptData);
pOptData += sizeof(USHORT);
// put in the network node
*pOptData++ = (BYTE)AtcpDefaultRouter.ata_Node;
break;
default:
ATCP_DBGPRINT(("atcpPrepareResponse: opt %d ignored\n",OptionType));
ATCP_ASSERT(0);
break;
}
if (fIncludeThisOption)
{
BytesLeftInSendBuf -= OptDataLen;
pResponse->Type = (BYTE)OptionType;
pResponse->Length = OptDataLen + 2; // 2 = 1 Type byte + 1 Length byte
pResponse = (PPP_OPTION UNALIGNED *)
((BYTE* )pResponse + pResponse->Length);
}
}
HostToWireFormat16( (USHORT)((PBYTE)pResponse - (PBYTE)pSendBuf),
pSendBuf->Length );
pSendBuf->Code = (fNakingSomething) ? CONFIG_NAK :
((fRequestingSomething)? CONFIG_REQ : CONFIG_ACK);
#if 0
if (pSendBuf->Code == CONFIG_REQ)
{
ATCP_DUMP_BYTES("atcpParseRequest: Sending our request:",
&pSendBuf->Data[0],
(DWORD)WireToHostFormat16( pSendBuf->Length)-4);
}
else if (pSendBuf->Code == CONFIG_NAK)
{
ATCP_DUMP_BYTES("atcpParseRequest: Nak'ing these options:",
&pSendBuf->Data[0],
(DWORD)WireToHostFormat16( pSendBuf->Length)-4);
}
else
{
ATCP_DUMP_BYTES("atcpParseRequest: Ack packet from us to client:",
&pSendBuf->Data[0],
(DWORD)WireToHostFormat16( pSendBuf->Length)-4);
}
#endif
return(NO_ERROR);
}
//***
//
// Function: atcpCloseAtalkConnection
// This routine tells the stack to close this ATCP connection
//
// Parameters: pAtcpConn - the connection to close
//
// Return: result of the operation
//
//***$
DWORD
atcpCloseAtalkConnection(
IN PATCPCONN pAtcpConn
)
{
DWORD dwRetCode=NO_ERROR;
// tell the stack that this connection is going away!
dwRetCode = atcpAtkSetup(pAtcpConn, IOCTL_ATCP_CLOSE_CONNECTION);
return(dwRetCode);
}
#if DBG
//***
//
// Function: atcpDumpBytes
// DEBUG only: This routine dumps out a given packet to debugger
//
// Parameters: Str - string, if any, to be printed out
// Packet - packet!
// PacketLen - how big is the packet
//
// Return: none
//
//***$
VOID
atcpDumpBytes(
IN PBYTE Str,
IN PBYTE Packet,
IN DWORD PacketLen
)
{
DWORD i;
if (Str)
{
DbgPrint("%s: Packet size %ld\n ",Str,PacketLen);
}
else
{
DbgPrint("Packet size %ld\n ",PacketLen);
}
for (i=0; i<PacketLen; i++)
{
DbgPrint("%x ",Packet[i]);
}
DbgPrint("\n");
}
#endif