From 7dd2be9ae23331f4d51422fbff9c964d18d893bb Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sat, 8 Apr 2017 23:40:41 -0500 Subject: [PATCH] Patch NBPLookupName to map IP address or domain name to AppleTalk-style address. --- atipmapping.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++ atipmapping.h | 3 + cmdproc.asm | 11 ++++ cmdproc.h | 1 + installcmds.c | 1 + session.h | 4 ++ tcpconnection.c | 2 + 7 files changed, 174 insertions(+) diff --git a/atipmapping.c b/atipmapping.c index 1d6168c..6a7523e 100644 --- a/atipmapping.c +++ b/atipmapping.c @@ -1,5 +1,157 @@ #pragma noroot +#include +#include +#include +#include +#include +#include #include "atipmapping.h" +#include "asmglue.h" +#include "aspinterface.h" struct ATIPMapping atipMapping; + +#define DEFAULT_DSI_PORT 548 + +static char ATIPTypeName[] = "\pAFPServer"; +static char ATIPZoneName[] = "\pAFP over TCP"; + +// Next numbers to use for new mappings +static int nextNode = 1; +static int nextSocket = 1; + +#define return_error(x) do { \ + commandRec->result = (x); \ + commandRec->actualMatch = 0; \ + RestoreStateReg(stateReg); \ + return; \ +} while (0) + +#pragma databank 1 +void DoLookupName(NBPLookupNameRec *commandRec) { + cvtRec hostInfo; + dnrBuffer dnrInfo; + Byte *curr, *dest; + unsigned int count, nameLen; + NBPLUNameBufferRec *resultBuf; + LongWord initialTime; + Word stateReg; + + stateReg = ForceRomIn(); + + // TODO support async calls + if (commandRec->async) + return_error(atSyncErr); + + // Length needed for result, assuming the request is for our type/zone + count = offsetof(NBPLUNameBufferRec, entityName) + + ((EntName*)commandRec->entityPtr)->buffer[0] + + ATIPTypeName[0] + ATIPZoneName[0]; + if (count > commandRec->bufferLength) + return_error(nbpBufferErr); + + resultBuf = (NBPLUNameBufferRec *)commandRec->bufferPtr; + + curr = &((EntName*)commandRec->entityPtr)->buffer[0]; + dest = &resultBuf->entityName.buffer[0]; + + // Copy object name into result buffer + nameLen = *curr; + for (count = 0; count <= nameLen; count++) { + *dest++ = *curr++; + } + + // Check that entity type and zone are what we want, + // and copy names to result buffer. + nameLen = *curr; + for (count = 0; count <= nameLen; count++) { + if (toupper(*curr++) != toupper(ATIPTypeName[count])) + goto passThrough; + *dest++ = ATIPTypeName[count]; + } + nameLen = *curr; + for (count = 0; count <= nameLen; count++) { + if (toupper(*curr++) != toupper(ATIPZoneName[count])) + goto passThrough; + *dest++ = ATIPTypeName[count]; + } + + if (TCPIPValidateIPString(&resultBuf->entityName.buffer[0])) { + TCPIPConvertIPToHex(&hostInfo, &resultBuf->entityName.buffer[0]); + resultBuf->enumerator = 0; + + // TCPIPConvertIPToHex seems not to give port, so get it this way + hostInfo.cvtPort = + TCPIPMangleDomainName(0, &resultBuf->entityName.buffer[0]); + } else { + hostInfo.cvtPort = + TCPIPMangleDomainName(0xE000, &resultBuf->entityName.buffer[0]); + TCPIPDNRNameToIP(&resultBuf->entityName.buffer[0], &dnrInfo); + if (toolerror()) + return_error(nbpNameErr); + + initialTime = GetTick(); + while (dnrInfo.DNRstatus == DNR_Pending) { + if (GetTick() - initialTime >= 15*60) + break; + TCPIPPoll(); + } + + // Re-copy object name into result buffer to undo mangling + curr = &((EntName*)commandRec->entityPtr)->buffer[0]; + dest = &resultBuf->entityName.buffer[0]; + nameLen = *curr; + for (count = 0; count <= nameLen; count++) { + *dest++ = *curr++; + } + + if (dnrInfo.DNRstatus == DNR_OK) { + hostInfo.cvtIPAddress = dnrInfo.DNRIPaddress; + resultBuf->enumerator = 1; + } else if (dnrInfo.DNRstatus == DNR_NoDNSEntry) { + return_error(0); // not really an error, but 0 results + } else { + TCPIPCancelDNR(&dnrInfo); + return_error(nbpNameErr); + } + } + + if (hostInfo.cvtPort == 0) + hostInfo.cvtPort = DEFAULT_DSI_PORT; + + for (count = 0; count < MAX_SESSIONS; count++) { + if (sessionTbl[count].atipMapping.ipAddr == hostInfo.cvtIPAddress + && sessionTbl[count].atipMapping.port == hostInfo.cvtPort) + { + atipMapping = sessionTbl[count].atipMapping; + goto haveMapping; + } + } + + atipMapping.ipAddr = hostInfo.cvtIPAddress; + atipMapping.port = hostInfo.cvtPort; + atipMapping.networkNumber = 0xFFFF; /* invalid/reserved */ + atipMapping.node = nextNode++; + atipMapping.socket = nextSocket++; + if (nextNode == 254) + nextNode = 1; + if (nextSocket == 255) + nextSocket = 1; + +haveMapping: + resultBuf->netNum = atipMapping.networkNumber; + resultBuf->nodeNum = atipMapping.node; + resultBuf->socketNum = atipMapping.socket; + commandRec->actualMatch = 1; + commandRec->result = 0; + RestoreStateReg(stateReg); + return; + +passThrough: + // TODO pass through to actual NBP + return_error(nbpNameErr); +} +#pragma databank 0 + +#undef return_error diff --git a/atipmapping.h b/atipmapping.h index 1dcac5d..dc26330 100644 --- a/atipmapping.h +++ b/atipmapping.h @@ -2,6 +2,7 @@ #define ATIPMAPPING_H #include +#include typedef struct ATIPMapping { /* AppleTalk address/socket */ @@ -16,4 +17,6 @@ typedef struct ATIPMapping { extern struct ATIPMapping atipMapping; +void DoLookupName(NBPLookupNameRec *commandRec); + #endif diff --git a/cmdproc.asm b/cmdproc.asm index 49ebb72..70abcb5 100644 --- a/cmdproc.asm +++ b/cmdproc.asm @@ -25,6 +25,17 @@ cmdProc start jml DispatchASPCommand end +nbpCmdProc start + lda 3,s + pha + lda 3,s + pha + lda cmdRecPtr + sta 4,s + lda cmdRecPtr+2 + sta 6,s + jml DoLookupName + end CallCompletionRoutine start phb diff --git a/cmdproc.h b/cmdproc.h index ca28fda..356a1f8 100644 --- a/cmdproc.h +++ b/cmdproc.h @@ -2,6 +2,7 @@ #define CMDPROC_H void cmdProc(void); +void nbpCmdProc(void); void CallCompletionRoutine(void *); #endif diff --git a/installcmds.c b/installcmds.c index e9b6942..fe1c62a 100644 --- a/installcmds.c +++ b/installcmds.c @@ -16,6 +16,7 @@ NewCmd newCmds[] = { {aspCloseSessionCommand, cmdProc}, {aspCommandCommand, cmdProc}, {aspWriteCommand, cmdProc}, + {nbpLookupNameCommand, nbpCmdProc}, {0, 0} }; diff --git a/session.h b/session.h index f9aca2c..bcae60d 100644 --- a/session.h +++ b/session.h @@ -3,6 +3,7 @@ #include #include "dsiproto.h" +#include "atipmapping.h" /* Common portion of records for the various SP... commands */ typedef struct SPCommandRec { @@ -54,6 +55,9 @@ typedef struct Session { /* Marinetti error codes, both the tcperr* value and any tool error */ Word tcperr; Word toolerr; + + /* AppleTalk<->IP address mapping used for this session */ + ATIPMapping atipMapping; } Session; #endif diff --git a/tcpconnection.c b/tcpconnection.c index a5ae92e..2f6351a 100644 --- a/tcpconnection.c +++ b/tcpconnection.c @@ -28,6 +28,8 @@ BOOLEAN StartTCPConnection(Session *sess) { return FALSE; } + sess->atipMapping = atipMapping; + if (TCPIPGetConnectStatus() == FALSE) { TCPIPConnect(NULL); if (toolerror()) {