AmendHub

Download:

jcs

/

detritus

/

amendments

/

1

*: Initial import, part 1


jcs made amendment 1 about 1 year ago
--- AddressXlation.h Sun May 15 22:02:59 2022 +++ AddressXlation.h Sun May 15 22:02:59 2022 @@ -0,0 +1,74 @@ +/* + AddressXlation.h + MacTCP name to address translation routines. + + Copyright Apple Computer, Inc. 1988 + All rights reserved + +*/ + +#ifndef __ADDRESSXLATION__ +#define __ADDRESSXLATION__ + +#include "MacTCP.h" + +#define NUM_ALT_ADDRS 4 + +struct hostInfo { + int _pad; /* XXX: i don't know why this is needed, but without it, + * StrToAddrProcPtr() returns everything shifted 2 bytes */ + int rtnCode; + char cname[255]; + unsigned long addr[NUM_ALT_ADDRS]; +}; + +enum AddrClasses { + A = 1, + NS, + CNAME = 5, + lastClass = 65535 +}; + +struct cacheEntryRecord { + char *cname; + unsigned short type; + enum AddrClasses class; + unsigned long ttl; + union { + char *name; + ip_addr addr; + } rdata; +}; + +typedef pascal void (*EnumResultProcPtr)(struct cacheEntryRecord *cacheEntryRecordPtr, + char *userDataPtr); +typedef pascal void (*ResultProcPtr)(struct hostInfo *hostInfoPtr, + char *userDataPtr); + +extern OSErr OpenResolver(char *fileName); +extern OSErr StrToAddr(char *hostName, struct hostInfo *hostInfoPtr, + ResultProcPtr resultProc, char *userDataPtr); +extern OSErr AddrToStr(unsigned long addr, char *addrStr); +extern OSErr EnumCache(EnumResultProcPtr enumResultProc, char *userDataPtr); +extern OSErr AddrToName(ip_addr addr, struct hostInfo *hostInfoPtr, + ResultProcPtr resultProc, char *userDataPtr); +extern OSErr CloseResolver(void); + +/* + * The above functions call into the dnr resource and pass the function id + * and function-specific arguments, so the compiler needs to know the types + */ +typedef OSErr (*OpenResolverProcPtr)(UInt32, char *); +typedef OSErr (*CloseResolverProcPtr)(UInt32); +typedef OSErr (*StrToAddrProcPtr)(UInt32, char *hostName, + struct hostInfo *hostInfoPtr, ResultProcPtr resultProc, + char *userDataPtr); +typedef OSErr (*AddrToStrProcPtr)(UInt32, unsigned long addr, + char *addrStr); +typedef OSErr (*EnumCacheProcPtr)(UInt32, EnumResultProcPtr enumResultProc, + char *userDataPtr); +typedef OSErr (*AddrToNameProcPtr)(UInt32, ip_addr addr, + struct hostInfo *hostInfoPtr, ResultProcPtr resultProc, + char *userDataPtr); + +#endif \ No newline at end of file --- dnr.c Mon Sep 30 15:36:50 2024 +++ dnr.c Mon Sep 30 15:36:50 2024 @@ -0,0 +1,274 @@ +/* + * DNR.c - DNR library for MPW + * + * (c) Copyright 1988 by Apple Computer. All rights reserved + * + * Modifications by Jim Matthews, Dartmouth College, 5/91 + */ + +#include <Folders.h> +#include "dnr.h" +#include "tcp.h" +#include "util.h" + +#define OPENRESOLVER 1 +#define CLOSERESOLVER 2 +#define STRTOADDR 3 +#define ADDRTOSTR 4 +#define ENUMCACHE 5 +#define ADDRTONAME 6 +#define HINFO 7 +#define MXINFO 8 + +short SearchFolderForDNRP(long targetType, long targetCreator, + short vRefNum, long dirID); +short OpenOurRF(void); + +Handle dnr = nil; + +/* + * SearchFolderForDNRP is called to search a folder for files that might + * contain the 'dnrp' resource + */ +short +SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, + long dirID) +{ + HParamBlockRec fi; + Str255 filename; + short refnum; + + fi.fileParam.ioCompletion = nil; + fi.fileParam.ioNamePtr = (StringPtr)&filename; + fi.fileParam.ioVRefNum = vRefNum; + fi.fileParam.ioDirID = dirID; + fi.fileParam.ioFDirIndex = 1; + + while (PBHGetFInfo(&fi, false) == noErr) { + /* scan system folder for driver resource files of specific type & creator */ + if (fi.fileParam.ioFlFndrInfo.fdType == targetType && + fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) { + /* found the MacTCP driver file? */ + refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm); + if (Get1IndResource('dnrp', 1)) + return refnum; + CloseResFile(refnum); + } + + /* check next file in system folder */ + fi.fileParam.ioFDirIndex++; + fi.fileParam.ioDirID = dirID; /* PBHGetFInfo() clobbers ioDirID */ + } + return -1; +} + +/* OpenOurRF is called to open the MacTCP driver resources */ +short +OpenOurRF(void) +{ + short refnum; + short vRefNum; + long dirID; + + /* first search Control Panels for MacTCP 1.1 */ + GetSystemSubfolder(kControlPanelFolderType, false, &vRefNum, &dirID); + refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID); + if (refnum != -1) + return (refnum); + + /* next search System Folder for MacTCP 1.0.x */ + GetSystemFolder(&vRefNum, &dirID); + refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID); + if (refnum != -1) + return (refnum); + + /* finally, search Control Panels for MacTCP 1.0.x */ + GetSystemSubfolder(kControlPanelFolderType, false, &vRefNum, &dirID); + refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID); + if (refnum != -1) + return (refnum); + + return -1; +} + +OSErr +OpenResolver(char *fileName) +{ + short refnum; + OSErr rc; + + if (dnr != nil) + /* resolver already loaded in */ + return (noErr); + + /* + * Open the MacTCP driver to get DNR resources. Search for it based on + * creator & type rather than simply file name. + */ + refnum = OpenOurRF(); + + /* + * Ignore failures since the resource may have been installed in the + * System file if running on a Mac 512Ke. + */ + + /* load in the DNR resource package */ + ResrvMem(16000L); /* s-dorner@uiuc.edu, 9/5/91 */ + dnr = Get1IndResource('dnrp', 1); + if (dnr == nil) { + /* can't open DNR */ + return (ResError()); + } + + DetachResource(dnr); + if (refnum != -1) { + CloseWD(refnum); + CloseResFile(refnum); + } + + /* lock the DNR resource since it cannot be relocated while opened */ + MoveHHi(dnr); + HLock(dnr); + + /* call open resolver */ + rc = ((OpenResolverProcPtr)*dnr)(OPENRESOLVER, fileName); + if (rc != noErr) { + /* problem with open resolver, flush it */ + HUnlock(dnr); + DisposHandle(dnr); + dnr = nil; + } + + return (rc); +} + +OSErr +CloseResolver(void) +{ + if (dnr == nil) + /* resolver not loaded error */ + return (notOpenErr); + + /* call close resolver */ + (void)((CloseResolverProcPtr)*dnr)(CLOSERESOLVER); + + /* release the DNR resource package */ + HUnlock(dnr); + DisposHandle(dnr); + dnr = nil; + + return (noErr); +} + +OSErr +StrToAddr(char *hostName, struct hostInfo *rtnStruct, + ResultProcPtr resultproc, char *userDataPtr) +{ + OSErr err; + + if (dnr == nil) + /* resolver not loaded error */ + return (notOpenErr); + + err = ((StrToAddrProcPtr)*dnr)(STRTOADDR, hostName, rtnStruct, + resultproc, userDataPtr); + return err; +} + +OSErr +AddrToStr(unsigned long addr, char *addrStr) +{ + if (dnr == nil) + /* resolver not loaded error */ + return (notOpenErr); + + (void)((AddrToStrProcPtr)*dnr)(ADDRTOSTR, addr, addrStr); + return (noErr); +} + +OSErr +EnumCache(EnumResultProcPtr enumResultProc, char *userDataPtr) +{ + if (dnr == nil) + /* resolver not loaded error */ + return (notOpenErr); + + return ((EnumCacheProcPtr)*dnr)(ENUMCACHE, enumResultProc, + userDataPtr); +} + +OSErr +AddrToName(ip_addr addr, struct hostInfo *hostInfoPtr, + ResultProcPtr resultProc, char *userDataPtr) +{ + if (dnr == nil) + /* resolver not loaded error */ + return (notOpenErr); + + return ((AddrToNameProcPtr)*dnr)(ADDRTONAME, addr, hostInfoPtr, + resultProc, userDataPtr); +} + +#if 0 +OSErr +HInfo(char *hostName, struct returnRec *returnRecPtr, long resultProc, + char *userDataPtr) +{ + if (dnr == nil) + /* resolver not loaded error */ + return (notOpenErr); + + return ((*dnr)(HINFO, hostName, returnRecPtr, resultProc, userDataPtr)); +} + +OSErr +MXInfo(char *hostName, struct returnRec *returnRecPtr, long resultProc, + char *userDataPtr) +{ + if (dnr == nil) + /* resolver not loaded error */ + return (notOpenErr); + + return ((*dnr)(MXINFO, hostName, returnRecPtr, resultProc, userDataPtr)); +} +#endif + +OSErr +DNSResolveName(char *name, unsigned long *ipAddress, void (*yielder)(void)) +{ + OSErr osErr; + struct hostInfo aHostInfo; + volatile int done = 0; + + osErr = OpenResolver(nil); + if (osErr) + return osErr; + + osErr = StrToAddr(name, &aHostInfo, (ResultProcPtr)StrToAddrMarkDone, + (char *)&done); + + if (osErr == cacheFault) { + /* StrToAddrMarkDone will set done when DNS resolution finishes */ + while (!done) { + if (yielder) + yielder(); + else + SystemTask(); + } + } + + if (aHostInfo.rtnCode == cacheFault && aHostInfo.addr[0] == 0) + /* consider 0.0.0.0 a bad answer */ + aHostInfo.rtnCode = authNameErr; + + if ((aHostInfo.rtnCode == noErr) || (aHostInfo.rtnCode == cacheFault)) { + /* use the first IP address for this host */ + *ipAddress = aHostInfo.addr[0]; + osErr = noErr; + } else + osErr = aHostInfo.rtnCode; + + /* leave resolver open for faster lookups in the future */ + + return osErr; +} \ No newline at end of file --- dnr.h Fri Aug 30 09:55:34 2024 +++ dnr.h Fri Aug 30 09:55:34 2024 @@ -0,0 +1,74 @@ +/* + AddressXlation.h + MacTCP name to address translation routines. + + Copyright Apple Computer, Inc. 1988 + All rights reserved + +*/ + +#ifndef __ADDRESSXLATION__ +#define __ADDRESSXLATION__ + +#include "MacTCP.h" + +#define NUM_ALT_ADDRS 4 + +struct hostInfo { + int _pad; /* XXX: i don't know why this is needed, but without it, + * StrToAddrProcPtr() returns everything shifted 2 bytes */ + int rtnCode; + char cname[255]; + unsigned long addr[NUM_ALT_ADDRS]; +}; + +enum AddrClasses { + A = 1, + NS, + CNAME = 5, + lastClass = 65535 +}; + +struct cacheEntryRecord { + char *cname; + unsigned short type; + enum AddrClasses class; + unsigned long ttl; + union { + char *name; + ip_addr addr; + } rdata; +}; + +typedef pascal void (*EnumResultProcPtr)(struct cacheEntryRecord *cacheEntryRecordPtr, + char *userDataPtr); +typedef pascal void (*ResultProcPtr)(struct hostInfo *hostInfoPtr, + char *userDataPtr); + +extern OSErr OpenResolver(char *fileName); +extern OSErr StrToAddr(char *hostName, struct hostInfo *hostInfoPtr, + ResultProcPtr resultProc, char *userDataPtr); +extern OSErr AddrToStr(unsigned long addr, char *addrStr); +extern OSErr EnumCache(EnumResultProcPtr enumResultProc, char *userDataPtr); +extern OSErr AddrToName(ip_addr addr, struct hostInfo *hostInfoPtr, + ResultProcPtr resultProc, char *userDataPtr); +extern OSErr CloseResolver(void); + +/* + * The above functions call into the dnr resource and pass the function id + * and function-specific arguments, so the compiler needs to know the types + */ +typedef OSErr (*OpenResolverProcPtr)(UInt32, char *); +typedef OSErr (*CloseResolverProcPtr)(UInt32); +typedef OSErr (*StrToAddrProcPtr)(UInt32, char *hostName, + struct hostInfo *hostInfoPtr, ResultProcPtr resultProc, + char *userDataPtr); +typedef OSErr (*AddrToStrProcPtr)(UInt32, unsigned long addr, + char *addrStr); +typedef OSErr (*EnumCacheProcPtr)(UInt32, EnumResultProcPtr enumResultProc, + char *userDataPtr); +typedef OSErr (*AddrToNameProcPtr)(UInt32, ip_addr addr, + struct hostInfo *hostInfoPtr, ResultProcPtr resultProc, + char *userDataPtr); + +#endif \ No newline at end of file --- MacTCP.h Wed Jul 13 17:14:33 2022 +++ MacTCP.h Wed Jul 13 17:14:33 2022 @@ -0,0 +1,877 @@ +/* + File: MacTCP.h + + Contains: TCP Manager Interfaces. + + Version: Technology: MacTCP 2.0.6 + Package: Universal Interfaces 2.1ß1 in “MPW Prerelease” on ETO #17 + + Copyright: © 1984-1995 by Apple Computer, Inc. + All rights reserved. + + Bugs?: If you find a problem with this file, use the Apple Bug Reporter + stack. Include the file and version information (from above) + in the problem description and send to: + Internet: apple.bugs@applelink.apple.com + AppleLink: APPLE.BUGS + +*/ + +#ifndef __MACTCP__ +#define __MACTCP__ + + +#ifndef __TYPES__ +#include <Types.h> +#endif + +#if 0 +#ifndef __APPLETALK__ +#include <AppleTalk.h> +#endif +#endif + +enum { + kPascalStackBased = 0, + kCStackBased = 0, + kThinkCStackBased = 0 +}; +#define SIZE_CODE(size) (0) +#define RESULT_SIZE(sizeCode) (0) +#define STACK_ROUTINE_PARAMETER(whichParam, sizeCode) (0) + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_ALIGN_SUPPORTED +#pragma options align=mac68k +#endif + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import on +#endif + +/* +Developer Notes: + 0. This MacTCP header replaces what used to be defined in the following header files + MacTCPCommonTypes.h + GetMyIPAddr.h + MiscIPPB.h + TCPPB.h + UDPPB.h + + When the various control calls are made to the ip driver, you must set up a + NewRoutineDescriptor for every non-nil completion routine and/or notifyProc parameter. + Otherwise, the 68K driver code, will not correctly call your routine. + 1. For ipctlGetAddr Control calls, use NewGetIPIOCompletionProc + to set up a GetIPIOCompletionUPP universal procptr to pass as + the ioCompletion parameter. + 2. For the ipctlEchoICMP and ipctlLAPStats Control calls, use + NewIPIOCompletion to set up a IPIOCompletionUPP universal procptr + to pass in the ioCompletion field of the parameter block. + 3. For TCPCreatePB Control calls, use NewTCPNotifyProc to set up a + TCPNotifyUPP universal procptr to pass in the notifyProc field + of the parameter block + 4. For all of the TCP Control calls using the TCPiopb parameter block, + use NewTCPIOCompletionProc to set up a TCPIOCompletionUPP + universal procptr to pass in the ioCompletion field of the paramter + block. + 5. For UDBCreatePB Control calls, use NewUDPNotifyProc to set up a + UDPNotifyUPP universal procptr to pass in the notifyProc field + of the parameter block + 6. For all of the UDP Control calls using the UDPiopb parameter block, + use NewUDPIOCompletionProc to set up a UDPIOCompletionUPP + universal procptr to pass in the ioCompletion field of the paramter + block. + 7. For all calls implementing a notifyProc or ioCompletion routine + which was set up using a NewTCPRoutineProc call, do not call + DisposeRoutineSDescriptor on the universal procptr until + after the completion or notify proc has completed. +*/ +/* MacTCP return Codes in the range -23000 through -23049 */ + +enum { + inProgress = 1, /* I/O in progress */ + ipBadLapErr = -23000, /* bad network configuration */ + ipBadCnfgErr = -23001, /* bad IP configuration error */ + ipNoCnfgErr = -23002, /* missing IP or LAP configuration error */ + ipLoadErr = -23003, /* error in MacTCP load */ + ipBadAddr = -23004, /* error in getting address */ + connectionClosing = -23005, /* connection is closing */ + invalidLength = -23006, + connectionExists = -23007, /* request conflicts with existing connection */ + connectionDoesntExist = -23008, /* connection does not exist */ + insufficientResources = -23009, /* insufficient resources to perform request */ + invalidStreamPtr = -23010, + streamAlreadyOpen = -23011, + connectionTerminated = -23012, + invalidBufPtr = -23013, + invalidRDS = -23014, + invalidWDS = -23014, + openFailed = -23015, + commandTimeout = -23016, + duplicateSocket = -23017 +}; + +/* Error codes from internal IP functions */ +enum { + ipDontFragErr = -23032, /* Packet too large to send w/o fragmenting */ + ipDestDeadErr = -23033, /* destination not responding */ + icmpEchoTimeoutErr = -23035, /* ICMP echo timed-out */ + ipNoFragMemErr = -23036, /* no memory to send fragmented pkt */ + ipRouteErr = -23037, /* can't route packet off-net */ + nameSyntaxErr = -23041, + cacheFault = -23042, + noResultProc = -23043, + noNameServer = -23044, + authNameErr = -23045, + noAnsErr = -23046, + dnrErr = -23047, + outOfMemory = -23048 +}; + +enum { + BYTES_16WORD = 2, /* bytes per = 16, bit ip word */ + BYTES_32WORD = 4, /* bytes per = 32, bit ip word */ + BYTES_64WORD = 8 /* bytes per = 64, bit ip word */ +}; + +/* 8-bit quantity */ +typedef unsigned char UInt8; +typedef signed char SInt8; +typedef UInt8 b_8; + +/* 16-bit quantity */ +typedef unsigned short UInt16; +typedef signed short SInt16; +typedef UInt16 b_16; + +/* 32-bit quantity */ +typedef unsigned long UInt32; +typedef signed long SInt32; +typedef UInt32 b_32; + +/* IP address is 32-bits */ +typedef b_32 ip_addr; + +struct ip_addrbytes { + union { + b_32 addr; + UInt8 byte[4]; + } a; +}; +typedef struct ip_addrbytes ip_addrbytes; + +struct wdsEntry { + unsigned short length; /* length of buffer */ + Ptr ptr; /* pointer to buffer */ +}; +typedef struct wdsEntry wdsEntry; + +struct rdsEntry { + unsigned short length; /* length of buffer */ + Ptr ptr; /* pointer to buffer */ +}; +typedef struct rdsEntry rdsEntry; + +typedef unsigned long BufferPtr; + +typedef unsigned long StreamPtr; + + +enum { + netUnreach = 0, + hostUnreach = 1, + protocolUnreach = 2, + portUnreach = 3, + fragReqd = 4, + sourceRouteFailed = 5, + timeExceeded = 6, + parmProblem = 7, + missingOption = 8, + lastICMPMsgType = 32767 +}; + +typedef unsigned short ICMPMsgType; + +typedef b_16 ip_port; + +struct ICMPReport { + StreamPtr streamPtr; + ip_addr localHost; + ip_port localPort; + ip_addr remoteHost; + ip_port remotePort; + short reportType; + unsigned short optionalAddlInfo; + unsigned long optionalAddlInfoPtr; +}; +typedef struct ICMPReport ICMPReport; + +/* csCode to get our IP address */ + +enum { + ipctlGetAddr = 15 +}; + +typedef void (*GetIPIOCompletionProcPtr)(struct GetAddrParamBlock *iopb); + +#if GENERATINGCFM +typedef UniversalProcPtr GetIPIOCompletionUPP; +#else +typedef GetIPIOCompletionProcPtr GetIPIOCompletionUPP; +#endif + +#define GetIPParamBlockHeader \ + struct QElem* qLink; \ + short qType; \ + short ioTrap; \ + Ptr ioCmdAddr; \ + GetIPIOCompletionUPP ioCompletion; \ + OSErr ioResult; \ + StringPtr ioNamePtr; \ + short ioVRefNum; \ + short ioCRefNum; \ + short csCode +struct GetAddrParamBlock { + struct QElem *qLink; + short qType; + short ioTrap; + Ptr ioCmdAddr; + GetIPIOCompletionUPP ioCompletion; + OSErr ioResult; + StringPtr ioNamePtr; + short ioVRefNum; + short ioCRefNum; + short csCode; /* standard I/O header */ + ip_addr ourAddress; /* our IP address */ + long ourNetMask; /* our IP net mask */ +}; +typedef struct GetAddrParamBlock GetAddrParamBlock; + +/* control codes */ + +enum { + ipctlEchoICMP = 17, /* send icmp echo */ + ipctlLAPStats = 19 /* get lap stats */ +}; + +typedef void (*IPIOCompletionProcPtr)(struct ICMPParamBlock *iopb); + +#if GENERATINGCFM +typedef UniversalProcPtr IPIOCompletionUPP; +#else +typedef IPIOCompletionProcPtr IPIOCompletionUPP; +#endif + +#define IPParamBlockHeader \ + struct QElem* qLink; \ + short qType; \ + short ioTrap; \ + Ptr ioCmdAddr; \ + IPIOCompletionUPP ioCompletion; \ + OSErr ioResult; \ + StringPtr ioNamePtr; \ + short ioVRefNum; \ + short ioCRefNum; \ + short csCode +struct ICMPParamBlock { + struct QElem *qLink; + short qType; + short ioTrap; + Ptr ioCmdAddr; + IPIOCompletionUPP ioCompletion; + OSErr ioResult; + StringPtr ioNamePtr; + short ioVRefNum; + short ioCRefNum; + short csCode; /* standard I/O header */ + short params[11]; + struct { + unsigned long echoRequestOut; /* time in ticks of when the echo request went out */ + unsigned long echoReplyIn; /* time in ticks of when the reply was received */ + struct rdsEntry echoedData; /* data received in responce */ + Ptr options; + unsigned long userDataPtr; + } icmpEchoInfo; +}; +typedef pascal void (*ICMPEchoNotifyProcPtr)(struct ICMPParamBlock *iopb); + +#if GENERATINGCFM +typedef UniversalProcPtr ICMPEchoNotifyUPP; +#else +typedef ICMPEchoNotifyProcPtr ICMPEchoNotifyUPP; +#endif + +struct IPParamBlock { + struct QElem *qLink; + short qType; + short ioTrap; + Ptr ioCmdAddr; + IPIOCompletionUPP ioCompletion; + OSErr ioResult; + StringPtr ioNamePtr; + short ioVRefNum; + short ioCRefNum; + short csCode; /* standard I/O header */ + union { + struct { + ip_addr dest; /* echo to IP address */ + wdsEntry data; + short timeout; + Ptr options; + unsigned short optLength; + ICMPEchoNotifyUPP icmpCompletion; + unsigned long userDataPtr; + } IPEchoPB; + struct { + struct LAPStats *lapStatsPtr; + } LAPStatsPB; + } csParam; +}; +union LAPStatsAddrXlation { + struct arp_entry *arp_table; + struct nbp_entry *nbp_table; +}; +struct LAPStats { + short ifType; + char *ifString; + short ifMaxMTU; + long ifSpeed; + short ifPhyAddrLength; + char *ifPhysicalAddress; + union LAPStatsAddrXlation AddrXlation; + short slotNumber; +}; +typedef struct LAPStats LAPStats; + +#ifdef __APPLETALK__ +struct nbp_entry { + ip_addr ip_address; /* IP address */ + AddrBlock at_address; /* matching AppleTalk address */ + Boolean gateway; /* TRUE if entry for a gateway */ + Boolean valid; /* TRUE if LAP address is valid */ + Boolean probing; /* TRUE if NBP lookup pending */ + SInt8 afiller; /* Filler for proper byte alignment */ + long age; /* ticks since cache entry verified */ + long access; /* ticks since last access */ + SInt8 filler[116]; /* for internal use only !!! */ +}; +#endif +struct Enet_addr { + b_16 en_hi; + b_32 en_lo; +}; +typedef struct Enet_addr Enet_addr; + +struct arp_entry { + short age; /* cache aging field */ + b_16 protocol; /* Protocol type */ + ip_addr ip_address; /* IP address */ + Enet_addr en_address; /* matching Ethernet address */ +}; +typedef struct arp_entry arp_entry; + +/* number of ARP table entries */ + +enum { + ARP_TABLE_SIZE = 20 +}; + +enum { + NBP_TABLE_SIZE = 20, /* number of NBP table entries */ + NBP_MAX_NAME_SIZE = 16 + 10 + 2 +}; + +/* Command codes */ +enum { + TCPCreate = 30, + TCPPassiveOpen = 31, + TCPActiveOpen = 32, + TCPSend = 34, + TCPNoCopyRcv = 35, + TCPRcvBfrReturn = 36, + TCPRcv = 37, + TCPClose = 38, + TCPAbort = 39, + TCPStatus = 40, + TCPExtendedStat = 41, + TCPRelease = 42, + TCPGlobalInfo = 43, + TCPCtlMax = 49 +}; + +enum { + TCPClosing = 1, + TCPULPTimeout = 2, + TCPTerminate = 3, + TCPDataArrival = 4, + TCPUrgent = 5, + TCPICMPReceived = 6, + lastEvent = 32767 +}; + +typedef unsigned short TCPEventCode; + + +enum { + TCPRemoteAbort = 2, + TCPNetworkFailure = 3, + TCPSecPrecMismatch = 4, + TCPULPTimeoutTerminate = 5, + TCPULPAbort = 6, + TCPULPClose = 7, + TCPServiceError = 8, + lastReason = 32767 +}; + +typedef unsigned short TCPTerminationReason; + +typedef pascal void (*TCPNotifyProcPtr)(StreamPtr tcpStream, unsigned short eventCode, Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg); + +#if GENERATINGCFM +typedef UniversalProcPtr TCPNotifyUPP; +#else +typedef TCPNotifyProcPtr TCPNotifyUPP; +#endif + +typedef unsigned short tcp_port; + +/* ValidityFlags */ + +enum { + timeoutValue = 0x80, + timeoutAction = 0x40, + typeOfService = 0x20, + precedence = 0x10 +}; + +/* TOSFlags */ +enum { + lowDelay = 0x01, + throughPut = 0x02, + reliability = 0x04 +}; + +struct TCPCreatePB { + Ptr rcvBuff; + unsigned long rcvBuffLen; + TCPNotifyUPP notifyProc; + Ptr userDataPtr; +}; +typedef struct TCPCreatePB TCPCreatePB; + +struct TCPOpenPB { + SInt8 ulpTimeoutValue; + SInt8 ulpTimeoutAction; + SInt8 validityFlags; + SInt8 commandTimeoutValue; + ip_addr remoteHost; + tcp_port remotePort; + ip_addr localHost; + tcp_port localPort; + SInt8 tosFlags; + SInt8 precedence; + Boolean dontFrag; + SInt8 timeToLive; + SInt8 security; + SInt8 optionCnt; + SInt8 options[40]; + Ptr userDataPtr; +}; +typedef struct TCPOpenPB TCPOpenPB; + +struct TCPSendPB { + SInt8 ulpTimeoutValue; + SInt8 ulpTimeoutAction; + SInt8 validityFlags; + Boolean pushFlag; + Boolean urgentFlag; + SInt8 filler; /* Filler for proper byte alignment */ + Ptr wdsPtr; + unsigned long sendFree; + unsigned short sendLength; + Ptr userDataPtr; +}; +typedef struct TCPSendPB TCPSendPB; + +/* for receive and return rcv buff calls */ +/* Note: the filler in the following structure is in a different location than */ +/* that specified in the Programmer's Guide. */ +struct TCPReceivePB { + SInt8 commandTimeoutValue; + Boolean markFlag; + Boolean urgentFlag; + SInt8 filler; /* Filler for proper byte alignment */ + Ptr rcvBuff; + unsigned short rcvBuffLen; + Ptr rdsPtr; + unsigned short rdsLength; + unsigned short secondTimeStamp; + Ptr userDataPtr; +}; +typedef struct TCPReceivePB TCPReceivePB; + +struct TCPClosePB { + SInt8 ulpTimeoutValue; + SInt8 ulpTimeoutAction; + SInt8 validityFlags; + SInt8 filler; /* Filler for proper byte alignment */ + Ptr userDataPtr; +}; +typedef struct TCPClosePB TCPClosePB; + +struct HistoBucket { + unsigned short value; + unsigned long counter; +}; +typedef struct HistoBucket HistoBucket; + + +enum { + NumOfHistoBuckets = 7 +}; + +enum { + ConnectionStateClosed = 0, + ConnectionStateListening = 2, + ConnectionStateSYNReceived = 4, + ConnectionStateSYNSent = 6, + ConnectionStateEstablished = 8, + ConnectionStateFINWait1 = 10, + ConnectionStateFINWait2 = 12, + ConnectionStateCloseWait = 14, + ConnectionStateClosing = 16, + ConnectionStateLastAck = 18, + ConnectionStateTimeWait = 20 +}; + +struct TCPConnectionStats { + unsigned long dataPktsRcvd; + unsigned long dataPktsSent; + unsigned long dataPktsResent; + unsigned long bytesRcvd; + unsigned long bytesRcvdDup; + unsigned long bytesRcvdPastWindow; + unsigned long bytesSent; + unsigned long bytesResent; + unsigned short numHistoBuckets; + struct HistoBucket sentSizeHisto[NumOfHistoBuckets]; + unsigned short lastRTT; + unsigned short tmrSRTT; + unsigned short rttVariance; + unsigned short tmrRTO; + SInt8 sendTries; + SInt8 sourchQuenchRcvd; +}; +typedef struct TCPConnectionStats TCPConnectionStats; + +struct TCPStatusPB { + SInt8 ulpTimeoutValue; + SInt8 ulpTimeoutAction; + long unused; + ip_addr remoteHost; + tcp_port remotePort; + ip_addr localHost; + tcp_port localPort; + SInt8 tosFlags; + SInt8 precedence; + SInt8 connectionState; + SInt8 filler; /* Filler for proper byte alignment */ + unsigned short sendWindow; + unsigned short rcvWindow; + unsigned short amtUnackedData; + unsigned short amtUnreadData; + Ptr securityLevelPtr; + unsigned long sendUnacked; + unsigned long sendNext; + unsigned long congestionWindow; + unsigned long rcvNext; + unsigned long srtt; + unsigned long lastRTT; + unsigned long sendMaxSegSize; + struct TCPConnectionStats *connStatPtr; + Ptr userDataPtr; +}; +typedef struct TCPStatusPB TCPStatusPB; + +struct TCPAbortPB { + Ptr userDataPtr; +}; +typedef struct TCPAbortPB TCPAbortPB; + +struct TCPParam { + unsigned long tcpRtoA; + unsigned long tcpRtoMin; + unsigned long tcpRtoMax; + unsigned long tcpMaxSegSize; + unsigned long tcpMaxConn; + unsigned long tcpMaxWindow; +}; +typedef struct TCPParam TCPParam; + +struct TCPStats { + unsigned long tcpConnAttempts; + unsigned long tcpConnOpened; + unsigned long tcpConnAccepted; + unsigned long tcpConnClosed; + unsigned long tcpConnAborted; + unsigned long tcpOctetsIn; + unsigned long tcpOctetsOut; + unsigned long tcpOctetsInDup; + unsigned long tcpOctetsRetrans; + unsigned long tcpInputPkts; + unsigned long tcpOutputPkts; + unsigned long tcpDupPkts; + unsigned long tcpRetransPkts; +}; +typedef struct TCPStats TCPStats; + +typedef StreamPtr *StreamPPtr; + +struct TCPGlobalInfoPB { + struct TCPParam *tcpParamPtr; + struct TCPStats *tcpStatsPtr; + StreamPPtr tcpCDBTable[1]; + Ptr userDataPtr; + unsigned short maxTCPConnections; +}; +typedef struct TCPGlobalInfoPB TCPGlobalInfoPB; + +typedef void (*TCPIOCompletionProcPtr)(struct TCPiopb *iopb); + +#if GENERATINGCFM +typedef UniversalProcPtr TCPIOCompletionUPP; +#else +typedef TCPIOCompletionProcPtr TCPIOCompletionUPP; +#endif + +struct TCPiopb { + SInt8 fill12[12]; + TCPIOCompletionUPP ioCompletion; + short ioResult; + Ptr ioNamePtr; + short ioVRefNum; + short ioCRefNum; + short csCode; + StreamPtr tcpStream; + union { + struct TCPCreatePB create; + struct TCPOpenPB open; + struct TCPSendPB send; + struct TCPReceivePB receive; + struct TCPClosePB close; + struct TCPAbortPB abort; + struct TCPStatusPB status; + struct TCPGlobalInfoPB globalInfo; + } csParam; +}; +typedef struct TCPiopb TCPiopb; + + +enum { + UDPCreate = 20, + UDPRead = 21, + UDPBfrReturn = 22, + UDPWrite = 23, + UDPRelease = 24, + UDPMaxMTUSize = 25, + UDPStatus = 26, + UDPMultiCreate = 27, + UDPMultiSend = 28, + UDPMultiRead = 29, + UDPCtlMax = 29 +}; + +enum { + UDPDataArrival = 1, + UDPICMPReceived = 2, + lastUDPEvent = 32767 +}; + +typedef unsigned short UDPEventCode; + +typedef pascal void (*UDPNotifyProcPtr)(StreamPtr udpStream, unsigned short eventCode, Ptr userDataPtr, struct ICMPReport *icmpMsg); + +#if GENERATINGCFM +typedef UniversalProcPtr UDPNotifyUPP; +#else +typedef UDPNotifyProcPtr UDPNotifyUPP; +#endif + +typedef unsigned short udp_port; + +/* for create and release calls */ +struct UDPCreatePB { + Ptr rcvBuff; + unsigned long rcvBuffLen; + UDPNotifyUPP notifyProc; + unsigned short localPort; + Ptr userDataPtr; + udp_port endingPort; +}; +typedef struct UDPCreatePB UDPCreatePB; + +struct UDPSendPB { + unsigned short reserved; + ip_addr remoteHost; + udp_port remotePort; + Ptr wdsPtr; + Boolean checkSum; + SInt8 filler; /* Filler for proper byte alignment */ + unsigned short sendLength; + Ptr userDataPtr; + udp_port localPort; +}; +typedef struct UDPSendPB UDPSendPB; + +/* for receive and buffer return calls */ +struct UDPReceivePB { + unsigned short timeOut; + ip_addr remoteHost; + udp_port remotePort; + Ptr rcvBuff; + unsigned short rcvBuffLen; + unsigned short secondTimeStamp; + Ptr userDataPtr; + ip_addr destHost; /* only for use with multi rcv */ + udp_port destPort; /* only for use with multi rcv */ +}; +typedef struct UDPReceivePB UDPReceivePB; + +struct UDPMTUPB { + unsigned short mtuSize; + ip_addr remoteHost; + Ptr userDataPtr; +}; +typedef struct UDPMTUPB UDPMTUPB; + +typedef struct UDPiopb UDPiopb; +typedef void (*UDPIOCompletionProcPtr)(struct UDPiopb *iopb); + +#if GENERATINGCFM +typedef UniversalProcPtr UDPIOCompletionUPP; +#else +typedef UDPIOCompletionProcPtr UDPIOCompletionUPP; +#endif + +struct UDPiopb { + SInt8 fill12[12]; + UDPIOCompletionUPP ioCompletion; + short ioResult; + Ptr ioNamePtr; + short ioVRefNum; + short ioCRefNum; + short csCode; + StreamPtr udpStream; + union { + struct UDPCreatePB create; + struct UDPSendPB send; + struct UDPReceivePB receive; + struct UDPMTUPB mtu; + } csParam; +}; + +enum { + uppGetIPIOCompletionProcInfo = kCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct GetAddrParamBlock*))), + uppIPIOCompletionProcInfo = kCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct ICMPParamBlock*))), + uppICMPEchoNotifyProcInfo = kPascalStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct ICMPParamBlock*))), + uppTCPNotifyProcInfo = kPascalStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(StreamPtr))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned short))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Ptr))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(unsigned short))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(struct ICMPReport*))), + uppTCPIOCompletionProcInfo = kCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct TCPiopb*))), + uppUDPNotifyProcInfo = kPascalStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(StreamPtr))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned short))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Ptr))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(struct ICMPReport*))), + uppUDPIOCompletionProcInfo = kCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct UDPiopb*))) +}; + +#if GENERATINGCFM +#define NewGetIPIOCompletionProc(userRoutine) \ + (GetIPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppGetIPIOCompletionProcInfo, GetCurrentArchitecture()) +#define NewIPIOCompletionProc(userRoutine) \ + (IPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppIPIOCompletionProcInfo, GetCurrentArchitecture()) +#define NewICMPEchoNotifyProc(userRoutine) \ + (ICMPEchoNotifyUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppICMPEchoNotifyProcInfo, GetCurrentArchitecture()) +#define NewTCPNotifyProc(userRoutine) \ + (TCPNotifyUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppTCPNotifyProcInfo, GetCurrentArchitecture()) +#define NewTCPIOCompletionProc(userRoutine) \ + (TCPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppTCPIOCompletionProcInfo, GetCurrentArchitecture()) +#define NewUDPNotifyProc(userRoutine) \ + (UDPNotifyUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUDPNotifyProcInfo, GetCurrentArchitecture()) +#define NewUDPIOCompletionProc(userRoutine) \ + (UDPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUDPIOCompletionProcInfo, GetCurrentArchitecture()) +#else +#define NewGetIPIOCompletionProc(userRoutine) \ + ((GetIPIOCompletionUPP) (userRoutine)) +#define NewIPIOCompletionProc(userRoutine) \ + ((IPIOCompletionUPP) (userRoutine)) +#define NewICMPEchoNotifyProc(userRoutine) \ + ((ICMPEchoNotifyUPP) (userRoutine)) +#define NewTCPNotifyProc(userRoutine) \ + ((TCPNotifyUPP) (userRoutine)) +#define NewTCPIOCompletionProc(userRoutine) \ + ((TCPIOCompletionUPP) (userRoutine)) +#define NewUDPNotifyProc(userRoutine) \ + ((UDPNotifyUPP) (userRoutine)) +#define NewUDPIOCompletionProc(userRoutine) \ + ((UDPIOCompletionUPP) (userRoutine)) +#endif + +#if GENERATINGCFM +#define CallGetIPIOCompletionProc(userRoutine, iopb) \ + CallUniversalProc((UniversalProcPtr)(userRoutine), uppGetIPIOCompletionProcInfo, (iopb)) +#define CallIPIOCompletionProc(userRoutine, iopb) \ + CallUniversalProc((UniversalProcPtr)(userRoutine), uppIPIOCompletionProcInfo, (iopb)) +#define CallICMPEchoNotifyProc(userRoutine, iopb) \ + CallUniversalProc((UniversalProcPtr)(userRoutine), uppICMPEchoNotifyProcInfo, (iopb)) +#define CallTCPNotifyProc(userRoutine, tcpStream, eventCode, userDataPtr, terminReason, icmpMsg) \ + CallUniversalProc((UniversalProcPtr)(userRoutine), uppTCPNotifyProcInfo, (tcpStream), (eventCode), (userDataPtr), (terminReason), (icmpMsg)) +#define CallTCPIOCompletionProc(userRoutine, iopb) \ + CallUniversalProc((UniversalProcPtr)(userRoutine), uppTCPIOCompletionProcInfo, (iopb)) +#define CallUDPNotifyProc(userRoutine, udpStream, eventCode, userDataPtr, icmpMsg) \ + CallUniversalProc((UniversalProcPtr)(userRoutine), uppUDPNotifyProcInfo, (udpStream), (eventCode), (userDataPtr), (icmpMsg)) +#define CallUDPIOCompletionProc(userRoutine, iopb) \ + CallUniversalProc((UniversalProcPtr)(userRoutine), uppUDPIOCompletionProcInfo, (iopb)) +#else +#define CallGetIPIOCompletionProc(userRoutine, iopb) \ + (*(userRoutine))((iopb)) +#define CallIPIOCompletionProc(userRoutine, iopb) \ + (*(userRoutine))((iopb)) +#define CallICMPEchoNotifyProc(userRoutine, iopb) \ + (*(userRoutine))((iopb)) +#define CallTCPNotifyProc(userRoutine, tcpStream, eventCode, userDataPtr, terminReason, icmpMsg) \ + (*(userRoutine))((tcpStream), (eventCode), (userDataPtr), (terminReason), (icmpMsg)) +#define CallTCPIOCompletionProc(userRoutine, iopb) \ + (*(userRoutine))((iopb)) +#define CallUDPNotifyProc(userRoutine, udpStream, eventCode, userDataPtr, icmpMsg) \ + (*(userRoutine))((udpStream), (eventCode), (userDataPtr), (icmpMsg)) +#define CallUDPIOCompletionProc(userRoutine, iopb) \ + (*(userRoutine))((iopb)) +#endif + + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import off +#endif + +#if PRAGMA_ALIGN_SUPPORTED +#pragma options align=reset +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __MACTCP__ */ --- tcp.c Mon Sep 23 15:19:30 2024 +++ tcp.c Mon Sep 23 15:19:30 2024 @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2020 joshua stein <jcs@jcs.org> + * Copyright (c) 1990-1992 by the University of Illinois Board of Trustees + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "tcp.h" + +#define RCV_BUFFER_SIZE 1024 +#define TCP_BUFFER_SIZE 8192 +#define OPEN_TIMEOUT 60 + +short gIPPDriverRefNum; + +static short _TCPAtexitInstalled = 0; +static StreamPtr _TCPStreams[10] = { 0 }; + +void _TCPAtexit(void); + +OSErr +_TCPInit(void) +{ + ParamBlockRec pb; + OSErr osErr; + + memset(&pb, 0, sizeof(pb)); + + gIPPDriverRefNum = -1; + + pb.ioParam.ioCompletion = 0; + pb.ioParam.ioNamePtr = "\p.IPP"; + pb.ioParam.ioPermssn = fsCurPerm; + + osErr = PBOpen(&pb, false); + if (noErr == osErr) + gIPPDriverRefNum = pb.ioParam.ioRefNum; + + if (!_TCPAtexitInstalled) { + _atexit(_TCPAtexit); + _TCPAtexitInstalled = 1; + } + + return osErr; +} + +void +_TCPAtexit(void) +{ + short n; + TCPiopb pb = { 0 }; + + for (n = 0; n < (sizeof(_TCPStreams) / sizeof(_TCPStreams[0])); n++) { + if (_TCPStreams[n] != 0) { + _TCPAbort(&pb, _TCPStreams[n], nil, nil, false); + _TCPRelease(&pb, _TCPStreams[n], nil, nil, false); + _TCPStreams[n] = 0; + } + } +} + +OSErr +_TCPGetOurIP(ip_addr *ip, long *netMask) +{ + OSErr osErr; + GetAddrParamBlock pb; + + memset(&pb, 0, sizeof(pb)); + + pb.csCode = ipctlGetAddr; + pb.ioCRefNum = gIPPDriverRefNum; + pb.ioResult = 1; + + osErr = PBControl((ParmBlkPtr)&pb, true); + while (pb.ioResult > 0) + ; + + if (pb.ioResult != noErr) + return pb.ioResult; + + if (ip != NULL) + *ip = pb.ourAddress; + if (netMask != NULL) + *netMask = pb.ourNetMask; + + return osErr; +} + +OSErr +_TCPCreate(TCPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, long rcvBufLen, + TCPNotifyProc aNotifyProc, Ptr userDataPtr, + TCPIOCompletionProc ioCompletion, Boolean async) +{ + OSErr osErr; + short n; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPCreate; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->ioResult = 1; + + pb->csParam.create.rcvBuff = rcvBufPtr; + pb->csParam.create.rcvBuffLen = rcvBufLen; + pb->csParam.create.notifyProc = aNotifyProc; + pb->csParam.create.userDataPtr = userDataPtr; + + osErr = PBControl((ParmBlkPtr)pb, async); + if (!async && (noErr == osErr)) { + *stream = pb->tcpStream; + + for (n = 0; n < (sizeof(_TCPStreams) / sizeof(_TCPStreams[0])); n++) { + if (_TCPStreams[n] == 0) { + _TCPStreams[n] = pb->tcpStream; + break; + } + } + } + + return osErr; +} + +/* listen for an incoming connection */ +OSErr +_TCPPassiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr *remoteIP, + tcp_port *remotePort, ip_addr *localIP, tcp_port *localPort, + Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async) +{ + OSErr osErr; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPPassiveOpen; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.open.ulpTimeoutAction = 1; /* abort half-open connection */ + pb->csParam.open.ulpTimeoutValue = 5; /* after 5 seconds */ + pb->csParam.open.validityFlags = 0xC0; + pb->csParam.open.commandTimeoutValue = 0; + pb->csParam.open.remoteHost = 0; + pb->csParam.open.remotePort = 0; + pb->csParam.open.localHost = 0; + pb->csParam.open.localPort = *localPort; + pb->csParam.open.tosFlags = 0x1; /* low delay */ + pb->csParam.open.precedence = 0; + pb->csParam.open.dontFrag = 0; + pb->csParam.open.timeToLive = 0; + pb->csParam.open.security = 0; + pb->csParam.open.optionCnt = 0; + pb->csParam.open.userDataPtr = userData; + + osErr = PBControl((ParmBlkPtr) pb, async); + if (!async && (osErr == noErr)) { + if (remoteIP) + *remoteIP = pb->csParam.open.remoteHost; + if (remotePort) + *remotePort = pb->csParam.open.remotePort; + if (localIP) + *localIP = pb->csParam.open.localHost; + *localPort = pb->csParam.open.localPort; + } + + return osErr; +} + +/* make an outgoing connection */ +OSErr +_TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr remoteIP, + tcp_port remotePort, ip_addr *localIP, tcp_port *localPort, + Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async) +{ + OSErr osErr; + short index; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPActiveOpen; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.open.ulpTimeoutValue = 10; + pb->csParam.open.ulpTimeoutAction = 1; + pb->csParam.open.validityFlags = 0xC0; +#if 0 + /* not available with this csCode */ + pb->csParam.open.commandTimeoutValue = 30; +#endif + pb->csParam.open.remoteHost = remoteIP; + pb->csParam.open.remotePort = remotePort; + pb->csParam.open.localHost = 0; + pb->csParam.open.localPort = *localPort; + pb->csParam.open.tosFlags = 0; + pb->csParam.open.precedence = 0; + pb->csParam.open.dontFrag = 0; + pb->csParam.open.timeToLive = 0; + pb->csParam.open.security = 0; + pb->csParam.open.optionCnt = 0; + for (index = 0; index < sizeof(pb->csParam.open.options); ++index) + pb->csParam.open.options[index] = 0; + pb->csParam.open.userDataPtr = userData; + + osErr = PBControl((ParmBlkPtr) pb, async); + if (!async && (osErr == noErr)) { + *localIP = pb->csParam.open.localHost; + *localPort = pb->csParam.open.localPort; + } + + return osErr; +} + +OSErr +_TCPSend(TCPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async) +{ + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPSend; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.send.ulpTimeoutValue = 30; + pb->csParam.send.ulpTimeoutAction = 1; + pb->csParam.send.validityFlags = 0xC0; + pb->csParam.send.pushFlag = 1; /* XXX */ + pb->csParam.send.urgentFlag = 0; + pb->csParam.send.wdsPtr = (Ptr)wdsPtr; + pb->csParam.send.sendFree = 0; + pb->csParam.send.sendLength = 0; + pb->csParam.send.userDataPtr = userData; + + return PBControl((ParmBlkPtr)pb, async); +} + +OSErr +_TCPNoCopyRcv(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr, + unsigned short rdsLength, Ptr userData, TCPIOCompletionProc ioCompletion, + Boolean async) +{ + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPNoCopyRcv; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.receive.commandTimeoutValue = 30; + pb->csParam.receive.urgentFlag = 0; + pb->csParam.receive.markFlag = 0; + pb->csParam.receive.rdsPtr = rdsPtr; + pb->csParam.receive.rdsLength = rdsLength; + pb->csParam.receive.userDataPtr = userData; + + return PBControl((ParmBlkPtr)pb, async); +} + +OSErr +_TCPRcv(TCPiopb *pb, StreamPtr stream, Ptr rcvBufPtr, + unsigned short *rcvBufLen, Ptr userData, TCPIOCompletionProc ioCompletion, + Boolean async) +{ + OSErr osErr; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPRcv; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.receive.commandTimeoutValue = 30; + pb->csParam.receive.urgentFlag = 0; + pb->csParam.receive.markFlag = 0; + pb->csParam.receive.rcvBuff = rcvBufPtr; + pb->csParam.receive.rcvBuffLen = *rcvBufLen; + pb->csParam.receive.userDataPtr = userData; + + osErr = PBControl((ParmBlkPtr)pb, async); + if (!async) + *rcvBufLen = pb->csParam.receive.rcvBuffLen; + + return osErr; +} + +OSErr +_TCPBfrReturn(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async) +{ + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPRcvBfrReturn; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.receive.rdsPtr = rdsPtr; + pb->csParam.receive.userDataPtr = userData; + + return PBControl((ParmBlkPtr)pb, async); +} + +OSErr +_TCPClose(TCPiopb *pb, StreamPtr stream, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async) +{ + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPClose; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.close.ulpTimeoutValue = 30; + pb->csParam.close.ulpTimeoutAction = 1; + pb->csParam.close.validityFlags = 0xC0; + pb->csParam.close.userDataPtr = userData; + + return PBControl((ParmBlkPtr)pb, async); +} + +OSErr +_TCPAbort(TCPiopb *pb, StreamPtr stream, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async) +{ + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPAbort; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.abort.userDataPtr = userData; + + return PBControl((ParmBlkPtr)pb, async); +} + +OSErr +_TCPStatus(TCPiopb *pb, StreamPtr stream, struct TCPStatusPB *status, + Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async) +{ + OSErr osErr; + + pb->ioCompletion = ioCompletion; + pb->ioResult = 1; + pb->ioNamePtr = 0; + pb->ioVRefNum = 0; + pb->ioCRefNum = gIPPDriverRefNum; + pb->csCode = TCPStatus; + pb->tcpStream = stream; + pb->csParam.status.userDataPtr = userData; + + osErr = PBControl((ParmBlkPtr)pb, async); + if (!async && (noErr == osErr)) { + *status = pb->csParam.status; + } + + return osErr; +} + +OSErr +_TCPRelease(TCPiopb *pb, StreamPtr stream, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async) +{ + OSErr osErr; + short n; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = TCPRelease; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->tcpStream = stream; + pb->ioResult = 1; + + pb->csParam.status.userDataPtr = userData; + + osErr = PBControl((ParmBlkPtr)pb, async); + + for (n = 0; n < (sizeof(_TCPStreams) / sizeof(_TCPStreams[0])); n++) { + if (_TCPStreams[n] == stream) { + _TCPStreams[n] = 0; + break; + } + } + + return osErr; +} + +OSErr +_UDPMaxMTUSize(UDPiopb *pb, short *mtu) +{ + OSErr osErr; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = UDPMaxMTUSize; + pb->ioCRefNum = gIPPDriverRefNum; + pb->ioResult = 1; + + pb->csParam.mtu.remoteHost = (ip_addr)0; + + osErr = PBControl((ParmBlkPtr)pb, false); + + if (osErr == noErr) + *mtu = pb->csParam.mtu.mtuSize; + + return osErr; +} + +OSErr +_UDPCreate(UDPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, long rcvBufLen, + UDPNotifyProc aNotifyProc, Ptr userDataPtr, + UDPIOCompletionProc ioCompletion, Boolean async) +{ + OSErr osErr; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = UDPCreate; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->ioResult = 1; + + pb->csParam.create.rcvBuff = rcvBufPtr; + pb->csParam.create.rcvBuffLen = rcvBufLen; + pb->csParam.create.notifyProc = aNotifyProc; + pb->csParam.create.userDataPtr = userDataPtr; + + osErr = PBControl((ParmBlkPtr)pb, async); + if (!async && (noErr == osErr)) { + *stream = pb->udpStream; + } + + return osErr; +} + +OSErr +_UDPSend(UDPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, ip_addr remoteIP, + udp_port remotePort, Ptr userData, UDPIOCompletionProc ioCompletion, + Boolean async) +{ + memset(pb, 0, sizeof(*pb)); + + pb->csCode = UDPWrite; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->udpStream = stream; + pb->ioResult = 1; + + pb->csParam.send.remoteHost = remoteIP; + pb->csParam.send.remotePort = remotePort; + pb->csParam.send.wdsPtr = (Ptr)wdsPtr; + pb->csParam.send.checkSum = 0; + pb->csParam.send.sendLength = 0; + pb->csParam.send.userDataPtr = userData; + + return PBControl((ParmBlkPtr)pb, async); +} + +OSErr +_UDPRelease(UDPiopb *pb, StreamPtr stream, Ptr userData, + UDPIOCompletionProc ioCompletion, Boolean async) +{ + OSErr osErr; + + memset(pb, 0, sizeof(*pb)); + + pb->csCode = UDPRelease; + pb->ioCompletion = ioCompletion; + pb->ioCRefNum = gIPPDriverRefNum; + pb->udpStream = stream; + pb->ioResult = 1; + + //pb->csParam.status.userDataPtr = userData; + + osErr = PBControl((ParmBlkPtr)pb, async); + + return osErr; +} + + +/* convenience functions */ + +pascal void +StrToAddrMarkDone(struct hostInfo *hi, char *data) +{ + volatile int *done = (int *)data; + *done = 1; +} + +unsigned long +ip2long(char *ip) +{ + unsigned long address = 0; + short dotcount = 0, i; + unsigned short b = 0; + + for (i = 0; ip[i] != 0; i++) { + if (ip[i] == '.') { + if (++dotcount > 3) + return (0); + address <<= 8; + address |= b; + b = 0; + } else if (ip[i] >= '0' && ip[i] <= '9') { + b *= 10; + b += (ip[i] - '0'); + if (b > 255) + return (0); + } else + return (0); + } + + if (dotcount != 3) + return (0); + address <<= 8; + address |= b; + return address; +} + +void +long2ip(unsigned long num, char *ip) +{ + unsigned char *tmp = (unsigned char *)&num; + sprintf(ip, "%d.%d.%d.%d", tmp[0], tmp[1], tmp[2], tmp[3]); +} + +#define SOCKS_VERSION_SOCKS5 0x5 +#define SOCKS_METHOD_AUTH_NONE 0x0 +#define SOCKS_REQUEST_CONNECT 0x1 +#define SOCKS_REQUEST_ATYP_DOMAINNAME 0x3 +#define SOCKS_REPLY_SUCCESS 0x0 + +OSErr +SOCKS5TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr socks_ip, + tcp_port socks_port, char *remote_host, tcp_port remote_port, + ip_addr *local_ip, tcp_port *local_port, Ptr user_data, + TCPIOCompletionProc io_completion, Boolean async) +{ + OSErr err; + TCPStatusPB status_pb; + wdsEntry wds[2]; + char data[255] = { 0 }; + unsigned short len, remote_host_len; + + remote_host_len = strlen(remote_host); + if (remote_host_len + 7 > sizeof(data)) + return -1; + + err = _TCPActiveOpen(pb, stream, socks_ip, socks_port, local_ip, + local_port, user_data, io_completion, async); + if (err != noErr) + return err; + + data[0] = SOCKS_VERSION_SOCKS5; + data[1] = 1; /* nmethods */ + data[2] = SOCKS_METHOD_AUTH_NONE; + + memset(&wds, 0, sizeof(wds)); + wds[0].ptr = (Ptr)&data; + wds[0].length = 3; + + err = _TCPSend(pb, stream, wds, nil, nil, false); + if (err) + goto fail; + + for (;;) { + err = _TCPStatus(pb, stream, &status_pb, nil, nil, false); + if (err != noErr) + goto fail; + + if (status_pb.amtUnreadData >= 2) + break; + } + + len = 2; + err = _TCPRcv(pb, stream, (Ptr)&data, &len, nil, nil, false); + if (err != noErr) + goto fail; + + if (data[0] != SOCKS_VERSION_SOCKS5 || data[1] != SOCKS_METHOD_AUTH_NONE) + goto fail; + + len = 0; + data[len++] = SOCKS_VERSION_SOCKS5; + data[len++] = SOCKS_REQUEST_CONNECT; + data[len++] = 0; /* reserved */ + data[len++] = SOCKS_REQUEST_ATYP_DOMAINNAME; + data[len++] = remote_host_len; + memcpy(data + len, remote_host, remote_host_len); + len += remote_host_len; + data[len++] = (remote_port >> 8); + data[len++] = (remote_port & 0xff); + + memset(&wds, 0, sizeof(wds)); + wds[0].ptr = (Ptr)&data; + wds[0].length = len; + + err = _TCPSend(pb, stream, wds, nil, nil, false); + if (err) + goto fail; + + for (;;) { + err = _TCPStatus(pb, stream, &status_pb, nil, nil, false); + if (err != noErr) + goto fail; + + if (status_pb.amtUnreadData >= 7) + break; + } + + len = status_pb.amtUnreadData; + if (len > sizeof(data)) + len = sizeof(data); + err = _TCPRcv(pb, stream, (Ptr)&data, &len, nil, nil, false); + if (err != noErr) + goto fail; + + if (data[0] != SOCKS_VERSION_SOCKS5 || data[1] != SOCKS_REPLY_SUCCESS) + goto fail; + + return noErr; + +fail: + _TCPClose(pb, stream, nil, nil, false); + return err; +} --- tcp.h Fri Aug 30 09:56:02 2024 +++ tcp.h Fri Aug 30 09:56:02 2024 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1990-1992 by the University of Illinois Board of Trustees + */ + +#include "MacTCP.h" +#include "dnr.h" + +#ifndef __TCP_H__ +#define __TCP_H__ + +typedef struct +{ + Handle next; + struct hostInfo hi; +} HostInfoQ, *HostInfoQPtr, **HostInfoQHandle; + +typedef ProcPtr TCPNotifyProc; +typedef ProcPtr UDPNotifyProc; +typedef void (*TCPIOCompletionProc)(struct TCPiopb *iopb); +typedef void (*UDPIOCompletionProc)(struct UDPiopb *iopb); + +OSErr _TCPInit(void); +OSErr _TCPGetOurIP(ip_addr *ip, long *netMask); +OSErr _TCPCreate(TCPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, + long rcvBufLen, TCPNotifyProc aNotifyProc, Ptr userDataPtr, + TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPPassiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr *remoteIP, + tcp_port *remotePort, ip_addr *localIP, tcp_port *localPort, + Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr remoteIP, + tcp_port remotePort, ip_addr *localIP, tcp_port *localPort, + Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPSend(TCPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, + Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPNoCopyRcv(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr, + unsigned short rdsLength, Ptr userData, TCPIOCompletionProc ioCompletion, + Boolean async); +OSErr _TCPRcv(TCPiopb *pb, StreamPtr stream, Ptr rcvBufPtr, + unsigned short *rcvBufLen, Ptr userData, TCPIOCompletionProc ioCompletion, + Boolean async); +OSErr _TCPBfrReturn(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPClose(TCPiopb *pb, StreamPtr stream, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPAbort(TCPiopb *pb, StreamPtr stream, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPStatus(TCPiopb *pb, StreamPtr stream, struct TCPStatusPB *status, + Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async); +OSErr _TCPRelease(TCPiopb *pb, StreamPtr stream, Ptr userData, + TCPIOCompletionProc ioCompletion, Boolean async); + +OSErr _UDPMaxMTUSize(UDPiopb *pb, short *mtu); +OSErr _UDPCreate(UDPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, + long rcvBufLen, UDPNotifyProc aNotifyProc, Ptr userDataPtr, + UDPIOCompletionProc ioCompletion, Boolean async); +OSErr _UDPSend(UDPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, + ip_addr remoteIP, udp_port remotePort, Ptr userData, + UDPIOCompletionProc ioCompletion, Boolean async); +OSErr _UDPRelease(UDPiopb *pb, StreamPtr stream, Ptr userData, + UDPIOCompletionProc ioCompletion, Boolean async); + +OSErr DNSResolveName(char *name, unsigned long *ipAddress, + void (*yielder)(void)); +pascal void StrToAddrMarkDone(struct hostInfo *hi, char *data); + +unsigned long ip2long(char *ip); +void long2ip(unsigned long num, char *ip); + +OSErr SOCKS5TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr socks_ip, + tcp_port socks_port, char *remote_host, tcp_port remote_port, + ip_addr *local_ip, tcp_port *local_port, Ptr user_data, + TCPIOCompletionProc io_completion, Boolean async); + +#endif \ No newline at end of file