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 *)#
+ 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