Patch #: none yet Type: operational change Priority: none Modification: add support for AppleShareIP (AFP via TCP/IP) Submitted: David Hornsby IMPORTANT: IMPORTANT: This patch assumes CAP at patch level 198 IMPORTANT: This is an interim patch only. You will need to keep this IMPORTANT: patch file in order to reverse the code changes before patch IMPORTANT: 199 can be applied without error. When reversing this patch, IMPORTANT: you also need to manually remove the following files: IMPORTANT: rm cap60/applications/aufs/afpdsi.h IMPORTANT: rm cap60/applications/aufs/afpdsi.c IMPORTANT: rm cap60/etc/aufsIPFilter IMPORTANT: IMPORTANT: To use the TCP/IP functionality, you will require AppleShare IMPORTANT: Client version 3.7 or later, obtainable from Apple web sites IMPORTANT: IMPORTANT: http://appleshareip.apple.com/appleshareip/text/downloads.html IMPORTANT: File: cap60/applications/aufs/afpdsi.h File: cap60/applications/aufs/afpdsi.c File: cap60/applications/aufs/afpdt.c File: cap60/applications/aufs/afpfork.c File: cap60/applications/aufs/afpos.c File: cap60/applications/aufs/afps.h File: cap60/applications/aufs/afpserver.c File: cap60/applications/aufs/aufs.c File: cap60/applications/aufs/Makefile.m4 File: cap60/lib/afp/afppacks.c File: cap60/lib/cap/abasp.c File: cap60/lib/cap/absched.c File: cap60/etc/aufsIPFilter File: cap60/samples/ash.c File: cap60/man/AUFS.8 File: cap60/netat/afp.h File: cap60/netat/afpcmd.h *** applications/aufs/afpdsi.h.orig Mon Jul 14 12:20:23 1997 --- applications/aufs/afpdsi.h Fri Jul 11 20:07:07 1997 *************** *** 0 **** --- 1,108 ---- + /* + * $Author: djh $ $Date: 91/03/14 13:45:20 $ + * $Header: afpdsi.h,v 2.2 91/03/14 13:45:20 djh Exp $ + * $Revision: 2.2 $ + * + */ + + /* + * afpdsi.h - Data Stream Interface Includes + * + * AFP via a Transport Protocol (eg: TCP/IP) + * + * AppleTalk package for UNIX + * + * The following routines implement a lightweight extra + * layer between AFP (as embodied in the AUFS code), the + * original ASP via ATP layer, and delivery via other + * Transport Protocol layers, currently only TCP/IP. + * + * Refer: "AppleTalk Filing Protocol 2.2 & + * AFP over TCP/IP Specification" + * + * SSS == Server Session Socket + * SLS == Session Listening Socket + * WSS == Workstation Session Socket + * + * Copyright (c) 1997 The University of Melbourne + * David Hornsby + * + */ + + /* + * options + * + */ + #define DSI_OPT_REQQ 0x00 + #define DSI_OPT_ATTQ 0x01 + + #define DSI_OPT_REQLEN 4 + #define DSI_OPT_ATTLEN 4 + + /* + * quantum sizes + * + */ + #define DSI_ATTN_SIZ 2 + #define DSI_SRVR_CMD 1500 + #define DSI_SRVR_MAX 64*1024 + + /* + * the DSI header will be inserted in front of + * every AFP request or reply packet + * + */ + + struct dsi_hdr { + byte dsi_flags; /* used to determine packet type */ + #define DSI_REQ_FLAG 0x00 + #define DSI_REP_FLAG 0x01 + byte dsi_command; /* similar to ASP commands, except WrtCont */ + #define DSICloseSession 1 + #define DSICommand 2 + #define DSIGetStatus 3 + #define DSIOpenSession 4 + #define DSITickle 5 + #define DSIWrite 6 + #define DSIAttention 8 + word dsi_requestID; /* req ID on per-session basis, wraps */ + dword dsi_err_offset; /* error for reply, offset for write, else 0 */ + dword dsi_data_len; /* total data length following dsi_hdr */ + dword dsi_reserved; /* reserved for future, should be zero */ + }; + + /* + * per-session demux info + * + */ + struct dsi_sess { + int sesstype; + #define DSI_SESSION_ATALK 0x01 + #define DSI_SESSION_TCPIP 0x02 + int state; /* type of DSI data expected */ + #define DSI_STATE_HDR 0x01 + #define DSI_STATE_AFP 0x02 + #define DSI_STATE_DAT 0x03 + #define DSI_STATE_REP 0x04 + char *ptr; /* where we have to put incoming data */ + int lenleft; /* amount of data expected to arrive */ + int timeout; /* per-session tickle timer */ + #define DSI_TIMEOUT 5*4 + word sess_id_out; /* outgoing session ID (0-65535) */ + word sess_id_in; /* incoming session ID (0-65535) */ + struct dsi_hdr hdr; /* current incoming header (for reply) */ + ASPQE *aspqe; /* callback data for GetRequest etc. */ + }; + + /* + * IP filter list + * + */ + #define MAXIPFILTERS 100 + #define MAXIPFILTSIZ sizeof(struct ipFilter) + + struct ipFilter { + sword perm; + dword mask; + dword addr; + }; *** applications/aufs/afpdsi.c.orig Mon Jul 14 14:04:28 1997 --- applications/aufs/afpdsi.c Sun Apr 19 19:21:07 1998 *************** *** 0 **** --- 1,2029 ---- + /* + * $Author: djh $ $Date: 91/03/14 13:45:20 $ + * $Header: afpdsi.c,v 2.2 91/03/14 13:45:20 djh Exp $ + * $Revision: 2.2 $ + * + */ + + /* + * afpdsi.c - Data Stream Interface + * + * AFP via a Transport Protocol (eg: TCP/IP) + * + * AppleTalk package for UNIX + * + * The following routines implement a lightweight extra + * layer between AFP (as embodied in the AUFS code), the + * original ASP via ATP layer, and delivery via other + * Transport Protocol layers, currently only TCP/IP. + * + * Refer: "AppleTalk Filing Protocol 2.2 & + * AFP over TCP/IP Specification" + * + * SSS == Server Session Socket + * SLS == Session Listening Socket + * WSS == Workstation Session Socket + * + * Copyright (c) 1997 The University of Melbourne + * David Hornsby + * + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include "../../lib/cap/abasp.h" /* urk */ + #include "afpdsi.h" + + #ifdef HAVE_WRITEV + #include + #endif /* HAVE_WRITEV */ + + /* + * aufs AFP routines + * + */ + int dsiInit(); + int dsiGetSession(); + int dsiFork(); + int dsiTickleUserRoutine(); + int dsiGetRequest(); + int dsiWrtContinue(); + int dsiWrtReply(); + int dsiCmdReply(); + int dsiAttention(); + int dsiGetNetworkInfo(); + int dsiGetParms(); + int dsiCloseSession(); + int dsiShutdown(); + int dsiTCPIPCloseSLS(); + + /* + * AppleTalk Session Protocol routines + * (including some formerly 'private') + * + */ + int SPInit(); + int SPGetSession(); + int SPFork(); + int SPTickleUserRoutine(); + int SPGetRequest(); + int SPWrtContinue(); + int SPWrtReply(); + int SPCmdReply(); + int SPAttention(); + int SPGetNetworkInfo(); + int SPGetParms(); + int SPCloseSession(); + int SPShutdown(); + + ASPSSkt *aspsskt_find_slsrefnum(); + ASPSkt *aspskt_find_sessrefnum(); + ASPSkt *aspskt_find_active(); + ASPQE *create_aq(); + + void stopasptickle(); + void stop_ttimer(); + void delete_aq(); + void Timeout(); + + /* + * local TCP/IP routines + * + */ + int dsiTCPIPInit(); + int dsiTCPIPFork(); + int dsiTCPIPGetRequest(); + int dsiTCPWrtContinue(); + int dsiTCPIPWrtReply(); + int dsiTCPIPCmdReply(); + int dsiTCPIPReply(); + int dsiTCPIPTickleUserRoutine(); + int dsiTCPIPCloseSession(); + int dsiTCPIPAttention(); + int dsiTCPIPGetNetworkInfo(); + int dsiTCPIPWrite(); + int dsiTCPIPCloseSLS(); + + /* + * globals + * + */ + #ifdef DEBUG_AFP_CMD + extern FILE *dbg; + #endif /* DEBUG_AFP_CMD */ + + extern int errno; + extern int asip_enable; + extern char *dsiTCPIPFilter; + private struct dsi_sess *dsi_session = NULL; + + /* + * DSI transport-layer demultiplexing + * + */ + + /* + * Set up a Server Listening Socket (SLS) for both + * ASP/ATP and TCP/IP. + * + * SLSEntityIdentifier - server AppleTalk address + * ServiceStatusBlock - pointer to ServerInfo data + * ServiceStatusBlockSize - ServerInfo data size + * SLSRefNum - return a session RefNum + * + */ + + int + dsiInit(SLSEntityIdentifier, ServiceStatusBlock, + ServiceStatusBlockSize, SLSRefNum) + AddrBlock *SLSEntityIdentifier; /* SLS Net id */ + char *ServiceStatusBlock; /* block with status info */ + int ServiceStatusBlockSize; /* size of status info */ + int *SLSRefNum; /* sls ref num return place */ + { + int result; + extern int numasp; + + /* + * allocate & initialise space for DSI session data + * + */ + if (numasp <= 0) + return(-1); + + if ((dsi_session = (struct dsi_sess *) + malloc(sizeof(struct dsi_sess)*numasp)) == NULL) + return(-1); + + bzero((char *)dsi_session, sizeof(struct dsi_sess)*numasp); + + /* + * allocate SLSRefNum, initialise AppleTalk Session Protocol SLS + * + */ + result = SPInit(SLSEntityIdentifier, ServiceStatusBlock, + ServiceStatusBlockSize, SLSRefNum); + + #ifdef DEBUG_AFP_CMD + if (dbg != NULL) { + fprintf(dbg, "** SPInit(): (PID %d)\n", getpid()); + fprintf(dbg, "\tSLSRefNum: %d\n", *SLSRefNum); + fprintf(dbg, "\tServiceStatusBlockSize: %d\n", ServiceStatusBlockSize); + fprintf(dbg, "\tresult: %d\n", result); + fprintf(dbg, "\n\n"); + fflush(dbg); + } + #endif /* DEBUG_AFP_CMD */ + + if (result != noErr) + return(result); + + /* + * if enabled, setup TCP/IP SLS (uses same SLSRefNum) + * + */ + if (asip_enable) + if (dsiTCPIPInit(SLSEntityIdentifier, ServiceStatusBlock, + ServiceStatusBlockSize, SLSRefNum) != noErr) + asip_enable = 0; + + return(noErr); + } + + /* + * set up to wait for a new session to start + * + * SLSRefNum - Session Listening Socket RefNum + * SessRefNum - returns new session reference number + * comp - completion flag/error + * + */ + + int + dsiGetSession(SLSRefNum, SessRefNum, comp) + int SLSRefNum; + int *SessRefNum; + int *comp; + { + int result; + + /* + * get a session reference number, + * + */ + result = SPGetSession(SLSRefNum, SessRefNum, comp); + + #ifdef DEBUG_AFP_CMD + if (dbg != NULL) { + fprintf(dbg, "** SPGetSession(): (PID %d)\n", getpid()); + fprintf(dbg, "\tSLSRefNum: %d\n", SLSRefNum); + fprintf(dbg, "\tSessRefNum: %d\n", *SessRefNum); + fprintf(dbg, "\tcomp: %d\n", *comp); + fprintf(dbg, "\tresult: %d\n", result); + fprintf(dbg, "\n\n"); + fflush(dbg); + } + #endif /* DEBUG_AFP_CMD */ + + if (result != noErr) + return(result); + + /* + * assume that this session is going to be + * AppleTalk, until we find out otherwise + * (this depends on what type of OpenSession + * packet actually arrives) + * + */ + dsi_session[*SessRefNum].sesstype = DSI_SESSION_ATALK; + + /* + * initialise data structure for DSI state + * + */ + dsi_session[*SessRefNum].timeout = 0; + dsi_session[*SessRefNum].aspqe = NULL; + dsi_session[*SessRefNum].sess_id_in = 0; + dsi_session[*SessRefNum].sess_id_out = 0; + dsi_session[*SessRefNum].state = DSI_STATE_HDR; + dsi_session[*SessRefNum].lenleft = sizeof(struct dsi_hdr); + dsi_session[*SessRefNum].ptr = (char *)&dsi_session[*SessRefNum].hdr; + + return(noErr); + } + + /* + * fork and create new process to handle session + * + * SessRefNum - session reference number + * stickle - want server tickle + * ctickle - want client tickle + * + */ + + int + dsiFork(SessRefNum, stickle, ctickle) + int SessRefNum; + int stickle; + int ctickle; + { + /* + * if AppleTalk, hand off to Session Protocol + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPFork(SessRefNum, stickle, ctickle)); + + /* + * handle locally for TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPFork(SessRefNum, stickle, ctickle)); + + return(ParamErr); + } + + /* + * set the user-timeout routine and argument + * + * this needs to be handled in the parent + * process for AppleTalk connections and in + * the child process for TCP/IP connections + * + * 'pid' was obtained from the approriate fork() + * + */ + + int + dsiTickleUserRoutine(SessRefNum, routine, pid) + int SessRefNum; + int (*routine)(); + int pid; + { + /* + * AppleTalk + * + */ + if (pid) + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPTickleUserRoutine(SessRefNum, routine, pid)); + + /* + * TCP/IP + * + */ + if (!pid) + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPTickleUserRoutine(SessRefNum, routine, getpid())); + + return(noErr); + } + + /* + * set up to wait for a request on SSS + * + * SessRefNum - session reference number + * ReqBuff - request command buffer + * ReqBuffSize - request command buffer size + * ReqRefNum - pointer to a special command block + * SPReqType - returns command request type + * ActRcvdReqLen - returns command length + * comp - completion flag/error + * + */ + + int + dsiGetRequest(SessRefNum, ReqBuff, ReqBuffSize, + ReqRefNum, SPReqType, ActRcvdReqLen, comp) + int SessRefNum; + char *ReqBuff; + int ReqBuffSize; + ASPQE **ReqRefNum; + int *SPReqType; + int *ActRcvdReqLen; + int *comp; + { + /* + * AppleTalk + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPGetRequest(SessRefNum, ReqBuff, ReqBuffSize, + ReqRefNum, SPReqType, ActRcvdReqLen, comp)); + + /* + * TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPGetRequest(SessRefNum, ReqBuff, ReqBuffSize, + ReqRefNum, SPReqType, ActRcvdReqLen, comp)); + + return(ParamErr); + } + + /* + * 'read' data sent by client + * + * SessRefNum - session reference number + * ReqRefNum - client connection details (addr, TID) + * Buffer - final location for data + * BufferSize - maximum amount of data we can handle + * ActLenRcvd - actual amount of date received + * atptimeout - ATP get data timeout + * comp - completion flag/error + * + */ + + int + dsiWrtContinue(SessRefNum, ReqRefNum, Buffer, BufferSize, + ActLenRcvd, atptimeout, comp) + int SessRefNum; + ASPQE *ReqRefNum; + char *Buffer; + int BufferSize; + int *ActLenRcvd; + int atptimeout; + int *comp; + { + /* + * AppleTalk + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPWrtContinue(SessRefNum, ReqRefNum, Buffer, + BufferSize, ActLenRcvd, atptimeout, comp)); + + /* + * TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPWrtContinue(SessRefNum, ReqRefNum, Buffer, + BufferSize, ActLenRcvd, atptimeout, comp)); + + return(ParamErr); + } + + /* + * reply to a write request sent to our SSS + * + * SessRefNum - session reference number + * ReqRefNum - client connection details (addr, TID) + * CmdResult - return result + * CmdReplyData - return data + * CmdReplyDataSize - return data size + * comp - completion flag/error + * + */ + + int + dsiWrtReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp) + int SessRefNum; + ASPQE *ReqRefNum; + dword CmdResult; + char *CmdReplyData; + int CmdReplyDataSize; + int *comp; + { + /* + * AppleTalk + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPWrtReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp)); + + /* + * TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPWrtReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp)); + + return(ParamErr); + } + + /* + * Reply to a command request sent to our SSS + * + * SessRefNum - session reference number + * ReqRefNum - client connection details (addr, TID) + * CmdResult - return result + * CmdReplyData - return data + * CmdReplyDataSize - return data size + * comp - completion flag/error + * + */ + + int + dsiCmdReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp) + int SessRefNum; + ASPQE *ReqRefNum; + dword CmdResult; + char *CmdReplyData; + int CmdReplyDataSize; + int *comp; + { + /* + * AppleTalk + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPCmdReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp)); + + /* + * TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPCmdReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp)); + + return(ParamErr); + } + + /* + * send an Attention signal to WSS + * + * SessRefNum - session reference number + * AttentionCode - attention message + * atpretries - ATP Retries + * atptimeout - ATP Timeout + * comp - completion falg/error + * + */ + + int + dsiAttention(SessRefNum, AttentionCode, atpretries, atptimeout, comp) + int SessRefNum; + word AttentionCode; + int atpretries; + int *comp; + { + /* + * AppleTalk + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPAttention(SessRefNum, AttentionCode, + atpretries, atptimeout, comp)); + + /* + * TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPAttention(SessRefNum, AttentionCode, + atpretries, atptimeout, comp)); + + return(ParamErr); + } + + /* + * return remote address of session client + * + */ + + int + dsiGetNetworkInfo(SessRefNum, addr) + int SessRefNum; + AddrBlock *addr; + { + /* + * AppleTalk + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPGetNetworkInfo(SessRefNum, addr)); + + /* + * TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPGetNetworkInfo(SessRefNum, addr)); + + return(ParamErr); + } + + /* + * Get server operating parameters (these numbers are used + * to malloc() the appropriate amount of buffer space). + * + * MaxCmdSize - maximum single packet size + * QuantumSize - maximum outstanding data + * + * For ASP/ATP: + * MaxCmdSize = atpMaxData (578) + * QuantumSize = atpMaxData*atpMaxNum (578*8) + * + * For TCP/IP: + * MaxCmdSize = AFP Command Size (1500) + * QuantumSize = Data Chunk Size (65536) + * + */ + + int + dsiGetParms(MaxCmdSize, QuantumSize) + int *MaxCmdSize; + int *QuantumSize; + { + if (asip_enable) { + *MaxCmdSize = DSI_SRVR_CMD; + *QuantumSize = DSI_SRVR_MAX; + return(noErr); + } + + return(SPGetParms(MaxCmdSize, QuantumSize)); + } + + /* + * Close down a SSS + * + * SessRefNum - Session reference number + * atpretries - ATP Retries + * atptimeout - ATP Timeout + * comp - completion flag/error + * + */ + + int + dsiCloseSession(SessRefNum, atpretries, atptimeout, comp) + int SessRefNum; + int atpretries; + int atptimeout; + int *comp; + { + /* + * AppleTalk + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_ATALK) + return(SPCloseSession(SessRefNum, atpretries, atptimeout, comp)); + + /* + * TCP/IP + * + */ + if (dsi_session[SessRefNum].sesstype == DSI_SESSION_TCPIP) + return(dsiTCPIPCloseSession(SessRefNum, atpretries, atptimeout, comp)); + + return(ParamErr); + } + + /* + * shutdown session + * + * SessRefNum - session reference number + * + */ + + int + dsiShutdown(SessRefNum) + int SessRefNum; + { + /* + * clean up our session data + * + */ + if (dsi_session[SessRefNum].aspqe != NULL) + delete_aspaqe(dsi_session[SessRefNum].aspqe); + + dsi_session[SessRefNum].timeout = 0; + dsi_session[SessRefNum].aspqe = NULL; + dsi_session[SessRefNum].sess_id_in = 0; + dsi_session[SessRefNum].sess_id_out = 0; + dsi_session[SessRefNum].state = DSI_STATE_HDR; + dsi_session[SessRefNum].sesstype = DSI_SESSION_ATALK; + dsi_session[SessRefNum].lenleft = sizeof(struct dsi_hdr); + dsi_session[SessRefNum].ptr = (char *)&dsi_session[SessRefNum].hdr; + + /* + * then clean up the ASP stuff + * + */ + return(SPShutdown(SessRefNum)); + } + + #ifdef DEBUG_AFP_CMD + /* + * return descriptive command name string + * + */ + char * + dsi_cmd(cmd) + int cmd; + { + switch (cmd) { + case DSIGetStatus: + return("DSIGetStatus"); + break; + case DSIOpenSession: + return("DSIOpenSession"); + break; + case DSICommand: + return("DSICommand"); + break; + case DSIWrite: + return("DSIWrite"); + break; + case DSIAttention: + return("DSIAttention"); + break; + case DSITickle: + return("DSITickle"); + break; + case DSICloseSession: + return("DSICloseSession"); + break; + } + return("UNKNOWN"); + } + #endif /* DEBUG_AFP_CMD */ + + /* + * TCP/IP related routines + * + */ + + /* + * open and initialise TCP/IP SLS port + * + * "The interface will register the AFP server on a well-known + * (static) data stream port. In case of TCP, it will be TCP + * port number 548". + * + */ + + private int slsskt = -1; + private struct sockaddr_in lsin; + + int + dsiTCPIPInit(SLSEntityIdentifier, ServiceStatusBlock, + ServiceStatusBlockSize, SLSRefNum) + AddrBlock *SLSEntityIdentifier; /* SLS Net id */ + char *ServiceStatusBlock; /* block with status info */ + int ServiceStatusBlockSize; /* size of status info */ + int *SLSRefNum; /* sls ref num return place */ + { + int aport, len; + extern u_int asip_addr; + extern u_short asip_port; + private int dsiTCPIPSLSListener(); + struct protoent *t, *getprotobyname(); + + /* + * open a stream socket + * + */ + if ((slsskt = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return(slsskt); + + bzero((char *)&lsin, sizeof(lsin)); + + lsin.sin_family = AF_INET; + lsin.sin_port = htons(asip_port); + lsin.sin_addr.s_addr = htonl(asip_addr); + + /* + * want to send data as it becomes available + * + */ + len = 1; + t = getprotobyname("tcp"); + aport = (t == NULL) ? IPPROTO_TCP : t->p_proto; + setsockopt(slsskt, aport, TCP_NODELAY, (char *)&len, sizeof(int)); + + /* + * bind to ipaddr:port selected by AUFS -B option + * (defaults to INADDR_ANY:548) + * + */ + if (bind(slsskt, (struct sockaddr *)&lsin, sizeof(lsin)) != 0) { + close(slsskt); + return(-1); + } + + /* + * start listening for connection attempts + * + */ + if (listen(slsskt, 5) != 0) { + close(slsskt); + return(-1); + } + + /* + * register a callback routine to handle SLS connection requests + * + */ + fdlistener(slsskt, dsiTCPIPSLSListener, NULL, *SLSRefNum); + + return(noErr); + } + + /* + * fdlistener() callback routine for TCP/IP connection attempts + * + * accept() the connection and register a data listener for + * incoming connection/getstatus packets. + * + */ + + private int + dsiTCPIPSLSListener(fd, none, SLSRefNum) + int fd; + caddr_t none; + int SLSRefNum; + { + int len, acc; + int illegal = 0; + struct sockaddr_in rsin; + extern u_short asip_port; + private int dsiTCPIPIllegalIP(); + private int dsiTCPIPSSSListener(); + + len = sizeof(struct sockaddr_in); + if ((acc = accept(fd, (struct sockaddr *)&rsin, &len)) < 0) + return(acc); + + /* + * check our IP address filter for + * a disallowed source IP address + * + */ + if (!dsiTCPIPIllegalIP(&rsin)) + fdlistener(acc, dsiTCPIPSSSListener, NULL, SLSRefNum); + else + close(acc), illegal = 1; + + #ifdef DEBUG_AFP_CMD + if (dbg != NULL) { + fprintf(dbg, + "** AppleShareIP connection attempt to port %d from %s:%d (PID %d)\n", + asip_port, inet_ntoa(rsin.sin_addr), ntohs(rsin.sin_port), getpid()); + if (illegal) + fprintf(dbg, "** Rejected by IP address filter (%s)\n", dsiTCPIPFilter); + fprintf(dbg, "\n\n"); + fflush(dbg); + } + #endif /* DEBUG_AFP_CMD */ + + return(noErr); + } + + /* + * fdlistener() callback routine for incoming DSI requests + * + * "An AFP server expects two command types, that is, DSIOpenSession + * or DSIGetStatus after the data stream connection establishment. + * DSIOpenSession command confirms the clients commitment to open an + * actual DSI session. There is a 1-to-1 mapping between the data + * stream connection and a DSI session. DSIGetSTatus command replies + * the server status followed by the connection tear down by an AFP + * server". + * + * This handler is interested only in DSIGetStatus or DSIOpenSession + * requests. Once the session is open, we unregister the fd with this + * handler and re-register it with the generic session handler. + * + */ + + private int + dsiTCPIPSSSListener(fd, none, SLSRefNum) + int fd; + caddr_t none; + int SLSRefNum; + { + int len; + int optlen; + ASPSkt *as; + ASPSSkt *sas; + int SessRefNum; + char reply_opt[8]; + struct dsi_hdr hdr; + char *optptr, *reqst_opt; + private int dsiTCPIPSessListener(); + + /* + * hopefully there are at least sizeof(hdr) bytes available to read + * (of course, there may not be, but the extra trouble of keeping a + * per stream partial header for just DSIGetStatus and DSIOpenSession + * isn't really worth it). + * + */ + if ((len = read(fd, (char *)&hdr, sizeof(hdr))) != sizeof(hdr)) { + fdunlisten(fd); + close(fd); + return(-1); + } + + #ifdef DEBUG_AFP_CMD + if (dbg != NULL) { + char *dsi_cmd(); + fprintf(dbg, "<< AppleShareIP DSI header (PID %d, session startup):\n", + getpid()); + fprintf(dbg, "\tFlags: %02x (%s)\n", hdr.dsi_flags, + (hdr.dsi_flags == DSI_REQ_FLAG) ? "Request" : "REPLY!!"); + fprintf(dbg, "\tCommand: %02x (%s)\n", hdr.dsi_command, + dsi_cmd(hdr.dsi_command)); + fprintf(dbg, "\tRequestID: %d\n", ntohs(hdr.dsi_requestID)); + fprintf(dbg, "\tErrCode/DataOffset: %d\n", ntohl(hdr.dsi_err_offset)); + fprintf(dbg, "\tDataLength: %d\n", ntohl(hdr.dsi_data_len)); + fprintf(dbg, "\tReserved: %d\n\n\n", ntohl(hdr.dsi_reserved)); + fflush(dbg); + } + #endif /* DEBUG_AFP_CMD */ + + /* + * not interested in Replies + * (should be none) + * + */ + if (hdr.dsi_flags != DSI_REQ_FLAG) + return(noErr); + + /* + * process the request + * + */ + switch (hdr.dsi_command) { + case DSIGetStatus: + /* dig out saved server status info for this SLS */ + if ((sas = aspsskt_find_slsrefnum(SLSRefNum)) != NULL) { + hdr.dsi_flags = DSI_REP_FLAG; + hdr.dsi_err_offset = htonl(noErr); + hdr.dsi_data_len = htonl(sas->ssbl); + hdr.dsi_reserved = htonl(0x00000000); + /* send server status information */ + dsiTCPIPWrite(fd, &hdr, (char *)sas->ssb, sas->ssbl); + } + /* fall through */ + default: /* tear down connection */ + fdunlisten(fd); + close(fd); + break; + case DSIOpenSession: + /* search for SLS next waiting session */ + if ((as = aspskt_find_active(SLSRefNum)) == NULL) { + hdr.dsi_flags = DSI_REP_FLAG; + hdr.dsi_err_offset = htonl(ServerBusy); + hdr.dsi_data_len = htonl(0x00000000); + hdr.dsi_reserved = htonl(0x00000000); + dsiTCPIPWrite(fd, &hdr, NULL, 0); + fdunlisten(fd); + close(fd); + break; + } + /* check for incoming OpenSession options */ + if ((optlen = ntohl(hdr.dsi_data_len)) > 0) { + if ((reqst_opt = (char *)malloc(optlen)) != NULL) { + optptr = reqst_opt; + while (optlen > 0) { + if ((len = read(fd, optptr, optlen)) < 0) { + fdunlisten(fd); + close(fd); + break; + } + optlen -= len; + optptr += len; + } + /* + * one day we might actually care + * + dsi_parse_option(optptr); + * + */ + free(reqst_opt); + } + } + /* start session */ + as->ss = fd; + as->state = SP_STARTED; + SessRefNum = as->SessRefNum; + /* mark this session as type TCP/IP */ + dsi_session[SessRefNum].sesstype = DSI_SESSION_TCPIP; + /* set up state for this session */ + dsi_session[SessRefNum].state = DSI_STATE_HDR; + dsi_session[SessRefNum].lenleft = sizeof(struct dsi_hdr); + dsi_session[SessRefNum].ptr = (char *)&dsi_session[SessRefNum].hdr; + dsi_session[SessRefNum].sess_id_in = ntohs(hdr.dsi_requestID)+1; + dsi_session[SessRefNum].sess_id_out = 0; + dsi_session[SessRefNum].aspqe = NULL; + dsi_session[SessRefNum].timeout = 0; + /* set OpenSession reply option */ + optlen = DSI_OPT_REQLEN+2; + reply_opt[0] = DSI_OPT_REQQ; + reply_opt[1] = DSI_OPT_REQLEN; + reply_opt[2] = (DSI_SRVR_MAX >> 24) & 0xff; + reply_opt[3] = (DSI_SRVR_MAX >> 16) & 0xff; + reply_opt[4] = (DSI_SRVR_MAX >> 8) & 0xff; + reply_opt[5] = (DSI_SRVR_MAX) & 0xff; + /* setup response header */ + hdr.dsi_flags = DSI_REP_FLAG; + hdr.dsi_err_offset = htonl(noErr); + hdr.dsi_data_len = htonl(optlen); + hdr.dsi_reserved = htonl(0x00000000); + /* send OpenSession Reply */ + dsiTCPIPWrite(fd, &hdr, reply_opt, optlen); + /* move fd to session handler */ + fdunlisten(fd); + fdlistener(fd, dsiTCPIPSessListener, (caddr_t)as, SessRefNum); + *as->comp = noErr; + return(noErr); + break; + } + + return(noErr); + } + + /* + * data listener for opened sessions + * + * At any time the data listener can be in one of four states, + * waiting until the expected amount of data has arrived, or a + * reply has been sent, freeing the header for re-use: + * + * DSI_STATE_HDR - reading the 16-byte DSI header + * DSI_STATE_AFP - reading the AFP command data + * DSI_STATE_DAT - reading the DSIWrite data + * DSI_STATE_REP - waiting until reply is sent + * + */ + + private int + dsiTCPIPSessListener(fd, as, SessRefNum) + int fd; + ASPSkt *as; + int SessRefNum; + { + int len; + int comp; + char *ptr; + ASPQE *aspqe; + atpProto *ap; + struct dsi_hdr *hdr; + + /* + * better have a waiting request + * + */ + if ((aspqe = dsi_session[SessRefNum].aspqe) == NULL) { + logit(0, "Incoming TCP/IP data but no pending request"); + dsiTCPIPCloseSession(SessRefNum, 0, 0, &comp); + return(-1); + } + + /* + * ignore available data until reply is sent + * (reply uses the sessionID in DSI header) or + * dsiTCPIPWrtContinue() changes the state to + * DSI_STATE_DAT + * + */ + if (dsi_session[SessRefNum].state == DSI_STATE_REP) + return(noErr); + + /* + * read DSI header or data from the + * tcp/ip stream as it comes in + * + */ + len = dsi_session[SessRefNum].lenleft; + ptr = dsi_session[SessRefNum].ptr; + + if ((len = read(fd, ptr, len)) < 0) { + logit(0, "TCP/IP read() returned %d (errno %d)", len, errno); + dsiTCPIPCloseSession(SessRefNum, 0, 0, &comp); + *aspqe->comp = SessClosed; + return(len); + } + + dsi_session[SessRefNum].lenleft -= len; + dsi_session[SessRefNum].ptr += len; + + if (dsi_session[SessRefNum].lenleft > 0) + return(noErr); + + /* + * sanity check + * + */ + if (dsi_session[SessRefNum].lenleft < 0) { + logit(0, "mismatch in expected amount of read data"); + dsiTCPIPCloseSession(SessRefNum, 0, 0, &comp); + *aspqe->comp = SessClosed; + return(-1); + } + + hdr = &dsi_session[SessRefNum].hdr; + + /* + * finished reading something, deal with it + * + */ + switch (dsi_session[SessRefNum].state) { + case DSI_STATE_HDR: + /* now have a complete DSI hdr */ + if (ntohl(hdr->dsi_data_len) > 0) { + /* and AFP hdr to follow */ + ap = &aspqe->abr.proto.atp; + dsi_session[SessRefNum].ptr = ap->atpDataPtr; + if (hdr->dsi_command == DSIWrite && ntohl(hdr->dsi_err_offset) != 0) + dsi_session[SessRefNum].lenleft = ntohl(hdr->dsi_err_offset); + else + dsi_session[SessRefNum].lenleft = ntohl(hdr->dsi_data_len); + dsi_session[SessRefNum].state = DSI_STATE_AFP; + return(noErr); + break; + } + /* fall through */ + case DSI_STATE_AFP: + /* have DSI hdr and optional AFP header */ + dsi_session[SessRefNum].ptr = (char *)hdr; + dsi_session[SessRefNum].lenleft = sizeof(struct dsi_hdr); + if (hdr->dsi_flags == DSI_REQ_FLAG) + dsi_session[SessRefNum].state = DSI_STATE_REP; + else + dsi_session[SessRefNum].state = DSI_STATE_HDR; + break; + case DSI_STATE_DAT: + /* have all DSIWrite data, reset state, tell client */ + dsi_session[SessRefNum].aspqe = NULL; + dsi_session[SessRefNum].ptr = (char *)hdr; + dsi_session[SessRefNum].lenleft = sizeof(struct dsi_hdr); + dsi_session[SessRefNum].state = DSI_STATE_REP; + *aspqe->ActRcvdReqLen = ntohl(hdr->dsi_data_len); + *aspqe->ActRcvdReqLen -= ntohl(hdr->dsi_err_offset); + *aspqe->comp = noErr; + delete_aspaqe(aspqe); + return(noErr); + break; + default: + /* huh ? */ + break; + } + + /* + * process DSI header and optional AFP data + * + */ + + #ifdef DEBUG_AFP_CMD + if (dbg != NULL) { + char *dsi_cmd(); + fprintf(dbg, "<< AppleShareIP DSI header (PID %d, session #%d):\n", + getpid(), SessRefNum); + fprintf(dbg, "\tFlags: %02x (%s)\n", hdr->dsi_flags, + (hdr->dsi_flags == DSI_REQ_FLAG) ? "Request" : "Reply"); + fprintf(dbg, "\tCommand: %02x (%s)\n", hdr->dsi_command, + dsi_cmd(hdr->dsi_command)); + fprintf(dbg, "\tRequestID: %d\n", ntohs(hdr->dsi_requestID)); + fprintf(dbg, "\tErrCode/DataOffset: %d\n", ntohl(hdr->dsi_err_offset)); + fprintf(dbg, "\tDataLength: %d\n", ntohl(hdr->dsi_data_len)); + fprintf(dbg, "\tReserved: %d\n\n\n", ntohl(hdr->dsi_reserved)); + fflush(dbg); + } + #endif /* DEBUG_AFP_CMD */ + + /* + * reset tickle timer + * + */ + dsi_session[SessRefNum].timeout = 0; + + /* + * ignore packet replies, rely on TCP to + * deliver in-order, that's what it's for. + * + */ + if (hdr->dsi_flags == DSI_REP_FLAG) + return(noErr); + + /* + * must be request, check if incoming + * session ID is what we are expecting + * + */ + if (ntohs(hdr->dsi_requestID) != dsi_session[SessRefNum].sess_id_in) { + logit(0, "unexpected incoming TCP/IP session ID"); + *aspqe->comp = ParamErr; + return(-1); + } + dsi_session[SessRefNum].sess_id_in++; + + /* + * only 3 valid commands to pass on to client + * handle DSITickle locally, 'cause it's simple + * + */ + switch (hdr->dsi_command) { + case DSICommand: + case DSIWrite: + *aspqe->comp = noErr; + break; + case DSICloseSession: + *aspqe->comp = SessClosed; + break; + case DSITickle: + hdr->dsi_flags = DSI_REP_FLAG; + dsiTCPIPWrite(fd, hdr, NULL, 0); + dsi_session[SessRefNum].state = DSI_STATE_HDR; + return(noErr); + break; + default: + logit(0, "unexpected incoming DSI cond (%d)", hdr->dsi_command); + *aspqe->comp = ParamErr; + break; + } + + /* + * tell the client how much data + * came in and the command type + * + */ + if (hdr->dsi_command == DSIWrite && ntohl(hdr->dsi_err_offset) != 0) + *aspqe->ActRcvdReqLen = ntohl(hdr->dsi_err_offset); + else + *aspqe->ActRcvdReqLen = ntohl(hdr->dsi_data_len); + *aspqe->SPReqType = hdr->dsi_command; + *aspqe->ReqRefNum = aspqe; + + /* + * free previous GetRequest aspqe + * + */ + delete_aspaqe(aspqe); + dsi_session[SessRefNum].aspqe = NULL; + + return(noErr); + } + + /* + * fork and create new process to handle TCP/IP session + * + * SessRefNum - session reference number + * stickle - want server tickle + * ctickle - want client tickle + * + * In the server code (parent) close all but SLS + * In the child code forget about SLS, just listen + * for SSS requests + * + */ + + int + dsiTCPIPFork(SessRefNum, stickle, ctickle) + int SessRefNum; + int stickle; + int ctickle; + { + int i, pid; + ASPSSkt *sas; + extern int sqs; + ASPSkt *as, *bs; + extern int numasp; + private void dsiTCPIPTimer(); + + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) + return(-1); + + if (as->state != SP_STARTED) + return(-1); + + /* + * make a new process + * + */ + if ((pid = fork()) < 0) + return(pid); + + /* + * if in parent process: + * close SSS + * + * if in child process: + * close both SLS (AppleTalk and TCP/IP) + * start tickle timer for our client session + * stop tickle timers for sibling ATALK sessions + * + */ + if (pid) { + /* close SSS */ + if (as->ss != -1) { + fdunlisten(as->ss); + close(as->ss); + as->ss = -1; + } + as->state = SP_HALFCLOSED; + } else { /* in child */ + if (as->type != SP_SERVER) + return(noErr); + /* close TCP/IP SLS */ + dsiTCPIPCloseSLS(); + /* kill sibling AT timeouts */ + for (i = 0; i < numasp; i++) { + if (i != SessRefNum) { + if ((bs = aspskt_find_sessrefnum(i)) != NULL) { + if (bs->tickling) + stopasptickle(bs); + stop_ttimer(bs); + } + } + } + /* close AppleTalk SLS */ + if ((sas = aspsskt_find_slsrefnum(as->SLSRefNum)) != NULL) + ATPCloseSocket(sas->addr.skt); + /* set a new read quantum */ + sqs = DSI_SRVR_MAX; + /* start our tickle timer */ + Timeout(dsiTCPIPTimer, numasp, DSI_TIMEOUT); + } + + return(pid); + } + + /* + * set up to wait for a request on TCP/IP SSS + * + * SessRefNum - session reference number + * ReqBuff - request command buffer + * ReqBuffSize - request command buffer size + * ReqRefNum - pointer to a special command block + * SPReqType - returns command request type + * ActRcvdReqLen - returns command length + * comp - completion flag/error + * + */ + + int + dsiTCPIPGetRequest(SessRefNum, ReqBuff, ReqBuffSize, + ReqRefNum, SPReqType, ActRcvdReqLen, comp) + int SessRefNum; + char *ReqBuff; + int ReqBuffSize; + ASPQE **ReqRefNum; + int *SPReqType; + int *ActRcvdReqLen; + int *comp; + { + ASPSkt *as; + atpProto *ap; + ASPQE *aspqe; + + /* + * check state of connection + * and validity of descriptor + * + */ + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) { + *comp = ParamErr; + return(ParamErr); + } + if (as->state != SP_STARTED) { + *comp = SessClosed; + return(SessClosed); + } + if (as->ss == -1) { + *comp = ParamErr; + return(ParamErr); + } + + /* + * subsequent GetRequests from TREL_TIMEOUT code + * on this SessRefNum will never get a callback + * (because we don't need them for TCP/IP use) + * + */ + if (dsi_session[SessRefNum].aspqe != NULL) { + *comp = 1; + return(noErr); + } + + /* + * save GetRequest args for data arrival + * + */ + aspqe = create_aspaqe(); + + aspqe->type = tSPGetRequest; + aspqe->SessRefNum = SessRefNum; + aspqe->ReqRefNum = ReqRefNum; + aspqe->SPReqType = SPReqType; + aspqe->ActRcvdReqLen = ActRcvdReqLen; + aspqe->comp = comp; + + ap = &aspqe->abr.proto.atp; + ap->atpReqCount = ReqBuffSize; + ap->atpDataPtr = ReqBuff; + + dsi_session[SessRefNum].aspqe = aspqe; + + *comp = 1; + return(noErr); + } + + /* + * arrange to put the 'read' data into Buffer + * + * SessRefNum - session reference number + * ReqRefNum - client connection details (addr, TID) + * Buffer - final location for data + * BufferSize - maximum amount of data we can handle + * ActLenRcvd - actual amount of date received + * atptimeout - ATP get data timeout + * comp - completion flag/error + * + */ + + dsiTCPIPWrtContinue(SessRefNum, ReqRefNum, Buffer, + BufferSize, ActLenRcvd, atptimeout, comp) + int SessRefNum; + ASPQE *ReqRefNum; + char *Buffer; + int BufferSize; + int *ActLenRcvd; + int atptimeout; + int *comp; + { + ASPSkt *as; + ASPQE *aspqe; + struct dsi_hdr *hdr; + + /* + * sanity checks + * + */ + if (BufferSize < 0) { + *comp = ParamErr; + return(ParamErr); + } + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) { + *comp = ParamErr; + return(ParamErr); + } + if (as->state != SP_STARTED) { + *comp = SessClosed; + return(SessClosed); + } + if (as->ss == -1) { + *comp = ParamErr; + return(ParamErr); + } + + /* + * save WrtContinue args for + * completion of data arrival + * + */ + aspqe = create_aspaqe(); + + aspqe->type = tSPWrtContinue; + aspqe->SessRefNum = SessRefNum; + aspqe->ActRcvdReqLen = ActLenRcvd; + aspqe->comp = comp; + + /* + * reset state & continue data reads + * + */ + hdr = &dsi_session[SessRefNum].hdr; + dsi_session[SessRefNum].aspqe = aspqe; + dsi_session[SessRefNum].state = DSI_STATE_DAT; + dsi_session[SessRefNum].lenleft = ntohl(hdr->dsi_data_len); + dsi_session[SessRefNum].lenleft -= ntohl(hdr->dsi_err_offset); + dsi_session[SessRefNum].ptr = Buffer; + + *comp = 1; + return(noErr); + } + + /* + * reply to a write request sent to our TCP/IP SSS + * + * SessRefNum - session reference number + * ReqRefNum - client connection details (addr, TID) + * CmdResult - return result + * CmdReplyData - return data + * CmdReplyDataSize - return data size + * comp - completion flag/error + * + */ + + int + dsiTCPIPWrtReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp) + int SessRefNum; + ASPQE *ReqRefNum; + dword CmdResult; + char *CmdReplyData; + int CmdReplyDataSize; + int *comp; + { + return(dsiTCPIPReply(DSIWrite, SessRefNum, ReqRefNum, + CmdResult, CmdReplyData, CmdReplyDataSize, comp)); + } + + /* + * Reply to a command request sent to our TCP/IP SSS + * + * SessRefNum - session reference number + * ReqRefNum - client connection details (addr, TID) + * CmdResult - return result + * CmdReplyData - return data + * CmdReplyDataSize - return data size + * comp - completion flag/error + * + */ + + int + dsiTCPIPCmdReply(SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp) + int SessRefNum; + ASPQE *ReqRefNum; + dword CmdResult; + char *CmdReplyData; + int CmdReplyDataSize; + int *comp; + { + return(dsiTCPIPReply(DSICommand, SessRefNum, ReqRefNum, + CmdResult, CmdReplyData, CmdReplyDataSize, comp)); + } + + /* + * common reply code + * + */ + + int + dsiTCPIPReply(dsiType, SessRefNum, ReqRefNum, CmdResult, + CmdReplyData, CmdReplyDataSize, comp) + int dsiType; + int SessRefNum; + ASPQE *ReqRefNum; + dword CmdResult; + char *CmdReplyData; + int CmdReplyDataSize; + int *comp; + { + ASPSkt *as; + struct dsi_hdr hdr; + + /* + * some sanity checking + * + */ + if (CmdReplyDataSize < 0) { + *comp = ParamErr; + return(ParamErr); + } + if (CmdReplyDataSize > DSI_SRVR_MAX) { + *comp = SizeErr; + return(SizeErr); + } + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) { + *comp = ParamErr; + return(ParamErr); + } + if (as->state != SP_STARTED) { + *comp = ParamErr; + return(ParamErr); + } + if (as->ss == -1) { + *comp = ParamErr; + return(ParamErr); + } + + /* + * setup DSI response header + * (the requestID is already + * in network byte order) + * + */ + hdr.dsi_flags = DSI_REP_FLAG; + hdr.dsi_command = dsiType; + hdr.dsi_requestID = dsi_session[SessRefNum].hdr.dsi_requestID; + hdr.dsi_err_offset = htonl(CmdResult); + hdr.dsi_data_len = htonl(CmdReplyDataSize); + hdr.dsi_reserved = htonl(0x00000000); + + /* + * session hdr can be re-used now + * + */ + dsi_session[SessRefNum].state = DSI_STATE_HDR; + + /* + * send it ... + * + */ + if (dsiTCPIPWrite(as->ss, &hdr, CmdReplyData, CmdReplyDataSize) < 0) { + *comp = ParamErr; + return(ParamErr); + } + + *comp = noErr; + return(noErr); + } + + /* + * setup tickle timeout callback + * + */ + + int + dsiTCPIPTickleUserRoutine(SessRefNum, routine, arg) + int SessRefNum; + int (*routine)(); + int arg; + { + ASPSkt *as; + + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) + return(ParamErr); + + as->tickle_timeout_user = routine; + as->ttu_arg = arg; + + return(noErr); + } + + /* + * Close down a TCP/IP Service Socket socket + * + * SessRefNum - Session reference number + * atpretries - ATP Retries + * atptimeout - ATP Timeout + * comp - completion flag/error + * + */ + + private struct dsi_hdr shut_hdr; + + int + dsiTCPIPCloseSession(SessRefNum, atpretries, atptimeout, comp) + int SessRefNum; + int atpretries; + int atptimeout; + int *comp; + { + ASPSkt *as; + + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) { + *comp = ParamErr; + return(ParamErr); + } + + switch (as->state) { + case SP_STARTED: + break; + case SP_HALFCLOSED: + break; + default: + as->active = FALSE; /* aspskt_free(as); */ + return(noErr); + break; + } + + /* + * set up the DSI header + * + */ + shut_hdr.dsi_flags = DSI_REQ_FLAG; + shut_hdr.dsi_command = DSICloseSession; + shut_hdr.dsi_requestID = htons(dsi_session[SessRefNum].sess_id_out++); + shut_hdr.dsi_err_offset = htonl(0x00000000); + shut_hdr.dsi_data_len = htonl(0x00000000); + shut_hdr.dsi_reserved = htonl(0x00000000); + + /* + * and send it ... + * + */ + if (dsiTCPIPWrite(as->ss, &shut_hdr, NULL, 0) < 0) { + *comp = ParamErr; + return(ParamErr); + } + + as->state = SP_INACTIVE; + as->active = FALSE; /* aspskt_free(as); */ + + if (as->ss != -1) { + fdunlisten(as->ss); + close(as->ss); + as->ss = -1; + } + + *comp = noErr; + return(noErr); + } + + /* + * send a TCP/IP Attention signal to WSS + * + * SessRefNum - session reference number + * AttentionCode - attention message + * atpretries - ATP Retries + * atptimeout - ATP Timeout + * comp - completion falg/error + * + */ + + private struct dsi_hdr attn_hdr; + + int + dsiTCPIPAttention(SessRefNum, AttentionCode, atpretries, atptimeout, comp) + int SessRefNum; + word AttentionCode; + int atpretries; + int *comp; + { + ASPSkt *as; + char attn[2]; + + /* + * some sanity checking + * + */ + if (AttentionCode == 0x00) { + *comp = ParamErr; + return(ParamErr); + } + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) { + *comp = ParamErr; + return(ParamErr); + } + if (as->state == SP_STARTING) { + *comp = ParamErr; + return(ParamErr); + } + + /* + * set up the DSI attention header, + * + */ + attn_hdr.dsi_flags = DSI_REQ_FLAG; + attn_hdr.dsi_command = DSIAttention; + attn_hdr.dsi_requestID = htons(dsi_session[SessRefNum].sess_id_out++); + attn_hdr.dsi_err_offset = htonl(0x00000000); + attn_hdr.dsi_data_len = htonl(sizeof(attn)); + attn_hdr.dsi_reserved = htonl(0x00000000); + + /* + * the attention field + * + */ + attn[0] = AttentionCode >> 8; + attn[1] = AttentionCode & 0xff; + + /* + * and send it ... + * + */ + if (dsiTCPIPWrite(as->ss, &attn_hdr, attn, sizeof(attn)) < 0) { + *comp = ParamErr; + return(ParamErr); + } + + *comp = noErr; + return(noErr); + } + + /* + * return peer name of session client + * + * (NB: function return value is positive TCP/IP port number, + * to distinguish this from a real AppleTalk GetNetworkInfo + * call which returns noErr. The IP address is returned in + * the four bytes of the AddrBlock) + * + */ + + int + dsiTCPIPGetNetworkInfo(SessRefNum, addr) + int SessRefNum; + AddrBlock *addr; + { + ASPSkt *as; + struct sockaddr_in name; + int len = sizeof(struct sockaddr); + + if ((as = aspskt_find_sessrefnum(SessRefNum)) == NULL) + return(ParamErr); + + if (as->ss == -1) + return(ParamErr); + + if (getpeername(as->ss, (struct sockaddr *)&name, &len) != 0) + return(ParamErr); + + if (name.sin_family != AF_INET) + return(ParamErr); + + name.sin_addr.s_addr = ntohl(name.sin_addr.s_addr); + addr->net = ((name.sin_addr.s_addr & 0xff000000) >> 16); + addr->net |= ((name.sin_addr.s_addr & 0x00ff0000) >> 16); + addr->node = ((name.sin_addr.s_addr & 0x0000ff00) >> 8); + addr->skt = (name.sin_addr.s_addr & 0x000000ff); + + return(ntohs(name.sin_port)); + } + + /* + * write data to client via TCP/IP stream + * + * We deliberately don't use non-blocking I/O + * because the majority of the large data transfers + * happen in a process dedicated to a single client. + * + */ + + int + dsiTCPIPWrite(fd, hdr, data, len) + int fd; + struct dsi_hdr *hdr; + char *data; + int len; + { + int cc, cd; + + #ifdef DEBUG_AFP_CMD + if (dbg != NULL) { + char *dsi_cmd(); + fprintf(dbg, ">> AppleShareIP DSI header (PID %d)\n", getpid()); + fprintf(dbg, "\tFlags: %02x (%s)\n", hdr->dsi_flags, + (hdr->dsi_flags == DSI_REQ_FLAG) ? "Request" : "Reply"); + fprintf(dbg, "\tCommand: %02x (%s)\n", hdr->dsi_command, + dsi_cmd(hdr->dsi_command)); + fprintf(dbg, "\tRequestID: %d\n", ntohs(hdr->dsi_requestID)); + fprintf(dbg, "\tErrCode/DataOffset: %d\n", ntohl(hdr->dsi_err_offset)); + fprintf(dbg, "\tDataLength: %d\n", ntohl(hdr->dsi_data_len)); + fprintf(dbg, "\tReserved: %d\n", ntohl(hdr->dsi_reserved)); + fflush(dbg); + } + #endif /* DEBUG_AFP_CMD */ + + /* + * writev() is more efficient but + * is less portable than write() + * + */ + #ifdef HAVE_WRITEV + { struct iovec iov[2]; + iov[0].iov_base = (caddr_t)hdr; + iov[0].iov_len = sizeof(struct dsi_hdr); + iov[1].iov_base = (caddr_t)data; + iov[1].iov_len = len; + cc = writev(fd, iov, (data == NULL) ? 1 : 2); + } + #else /* HAVE_WRITEV */ + if ((cc = write(fd, (char *)hdr, sizeof(struct dsi_hdr))) >= 0) { + if (data != NULL) { + if ((cd = write(fd, data, len)) >= 0) + cc += cd; + else + cc = cd; + } + } + #endif /* HAVE_WRITEV */ + + #ifdef DEBUG_AFP_CMD + if (dbg != NULL) { + extern int errno; + if (cc < 0) + fprintf(dbg, "** dsiTCPIPWrite(): %d bytes returns %d (errno %d)", + len+sizeof(struct dsi_hdr), cc, errno); + fprintf(dbg, "\n\n\n"); + fflush(dbg); + } + #endif /* DEBUG_AFP_CMD */ + + return(cc); + } + + /* + * Tickle Timeout timer + * + */ + + private void + dsiTCPIPTimer(numsess) + int numsess; + { + int i; + ASPSkt *as; + static int inited = 0; + static struct dsi_hdr tick_hdr; + void Timeout(); + + /* + * set-up the invariant + * fields of the tickle hdr + * + */ + if (!inited) { + tick_hdr.dsi_flags = DSI_REQ_FLAG; + tick_hdr.dsi_command = DSITickle; + tick_hdr.dsi_err_offset = htonl(0x00000000); + tick_hdr.dsi_data_len = htonl(0x00000000); + tick_hdr.dsi_reserved = htonl(0x00000000); + inited = 1; + } + + /* + * check for idle TCP/IP sessions + * + */ + for (i = 0; i < numsess; i++) { + if (dsi_session[i].sesstype == DSI_SESSION_TCPIP) { + dsi_session[i].timeout += DSI_TIMEOUT; + if (dsi_session[i].timeout >= ASPCONNECTIONTIMEOUT) { + if ((as = aspskt_find_sessrefnum(i)) != NULL) { + if (as->tickle_timeout_user != NULL) + (*as->tickle_timeout_user)(i, as->ttu_arg); + else { /* no user routine */ + as->state = SP_INACTIVE; + as->active = FALSE; /* aspskt_free(as); */ + dsiShutdown(i); + } + } + } else { /* not timed out, but time to send a tickle ? */ + if ((dsi_session[i].timeout % (ASPTICKLETIMEOUT)) == 0) { + if ((as = aspskt_find_sessrefnum(i)) != NULL) { + tick_hdr.dsi_requestID = htons(dsi_session[i].sess_id_out++); + dsiTCPIPWrite(as->ss, &tick_hdr, NULL, 0); + } + } + } + } + } + + Timeout(dsiTCPIPTimer, numsess, DSI_TIMEOUT); + + return; + } + + /* + * close the SLS (called from either the + * AppleTalk or TCP/IP child processes) + * + */ + + int + dsiTCPIPCloseSLS() + { + if (slsskt != -1) { + fdunlisten(slsskt); + close(slsskt); + slsskt = -1; + } + + return(noErr); + } + + /* + * IP address filter + * + * compatible with, and stolen from, + * the ARNS remote access package + * + * http://www.cs.mu.OZ.AU/appletalk/atalk.html + * + */ + + private int ipFilters = 0; + private struct ipFilter *ipFilter = NULL; + + /* + * read the specified IP address filter file + * + */ + + private void + dsiTCPIPBuildFilterList() + { + FILE *fp; + char line[160]; + char *mask, *addr; + unsigned long inet_addr(); + + ipFilters = 0; + + if (dsiTCPIPFilter != NULL) { + if (ipFilter == NULL) + if ((ipFilter = + (struct ipFilter *)malloc(MAXIPFILTSIZ*MAXIPFILTERS)) == NULL) + return; + if ((fp = fopen(dsiTCPIPFilter, "r")) != NULL) { + while (fgets(line, sizeof(line), fp) != NULL) { + if (line[0] == '#') + continue; + if ((mask = (char *)index(line, '\n')) != NULL) + *mask = '\0'; + mask = line+1; + while (*mask != '\0' && isspace(*mask)) + mask++; /* skip spaces */ + addr = mask; + while (*addr != '\0' && !isspace(*addr)) + addr++; /* skip mask */ + while (*addr != '\0' && isspace(*addr)) + addr++; /* skip spaces */ + if (line[0] == '+' || line[0] == '*' || line[0] == '-') { + ipFilter[ipFilters].perm = line[0]; + ipFilter[ipFilters].addr = (*addr == '\0') ? 0L : inet_addr(addr); + ipFilter[ipFilters].mask = (*mask == '\0') ? 0L : inet_addr(mask); + if (++ipFilters >= MAXIPFILTERS) + break; + } + } + (void)fclose(fp); + } + } + + return; + } + + /* + * check the IP address filter, if any + * + */ + + private int + dsiTCPIPIllegalIP(from) + struct sockaddr_in *from; + { + int i; + u_long addr; + + dsiTCPIPBuildFilterList(); + + if (ipFilters == 0 + || ipFilter == NULL) + return(0); + + addr = from->sin_addr.s_addr; + + for (i = 0 ; i < ipFilters ; i++) { + if (ipFilter[i].addr != 0L) { + if ((addr & ipFilter[i].mask) == ipFilter[i].addr) + return(ipFilter[i].perm == '-'); + } else { + if ((addr & ipFilter[i].mask) == addr) + return(ipFilter[i].perm == '-'); + } + } + + return(0); + } *** applications/aufs/afpdt.c.orig Wed Sep 25 00:10:20 1996 --- applications/aufs/afpdt.c Mon Jul 7 17:01:14 1997 *************** *** 1170,1176 **** PrintIconInfo(adi.adi_fcreator,adi.adi_ftype); } ! err = SPWrtContinue(cno,reqref,icon,adi.adi_iconsize,&rcvlen,-1,&comp); if (err != noErr) { free((char *)icon); return(err); --- 1170,1176 ---- PrintIconInfo(adi.adi_fcreator,adi.adi_ftype); } ! err = dsiWrtContinue(cno,reqref,icon,adi.adi_iconsize,&rcvlen,-1,&comp); if (err != noErr) { free((char *)icon); return(err); *** applications/aufs/afpfork.c.orig Wed Sep 25 00:09:33 1996 --- applications/aufs/afpfork.c Mon Jul 7 17:43:35 1997 *************** *** 585,591 **** return(aeAccessDenied); } ! err = SPWrtContinue(cno,reqref,r,n_rrpkts*atpMaxData,&rcvlen,-1,&comp); if (err != noErr) return(err); do { abSleep(4,TRUE); } while (comp > 0); --- 585,591 ---- return(aeAccessDenied); } ! err = dsiWrtContinue(cno,reqref,r,n_rrpkts*atpMaxData,&rcvlen,-1,&comp); if (err != noErr) return(err); do { abSleep(4,TRUE); } while (comp > 0); *** applications/aufs/afpos.c.orig Wed Sep 25 00:10:24 1996 --- applications/aufs/afpos.c Wed Jul 9 11:39:02 1997 *************** *** 766,772 **** --- 766,776 ---- msg[i] = '\r'; } close(fd); + return(noErr); } + + sprintf(msg, ""); + return(noErr); } *** applications/aufs/afps.h.orig Wed Sep 25 00:10:19 1996 --- applications/aufs/afps.h Mon Mar 3 22:14:05 1997 *************** *** 247,252 **** --- 247,253 ---- #define AFPVersion1DOT1 110 #define AFPVersion2DOT0 200 #define AFPVersion2DOT1 210 + #define AFPVersion2DOT2 220 #ifdef APPLICATION_MANAGER struct flist { *** applications/aufs/afpserver.c.orig Wed Sep 25 00:10:23 1996 --- applications/aufs/afpserver.c Wed Jul 9 10:44:28 1997 *************** *** 47,52 **** --- 47,54 ---- /* assume included by param.h */ # include #endif + #include + #include #include #include #include *************** *** 97,103 **** private char *afpmtyp = "Unix"; ! #define AFPVERSZ (5*16) /* room for IndStr hold all versions */ /* define 1 more than needed just in case */ struct afpversionstruct { char *version_name; --- 99,105 ---- private char *afpmtyp = "Unix"; ! #define AFPVERSZ (6*16) /* room for IndStr hold all versions */ /* define 1 more than needed just in case */ struct afpversionstruct { char *version_name; *************** *** 107,112 **** --- 109,115 ---- {"AFPVersion 1.1", AFPVersion1DOT1}, {"AFPVersion 2.0", AFPVersion2DOT0}, {"AFPVersion 2.1", AFPVersion2DOT1}, + {"AFP2.2", AFPVersion2DOT2}, {NULL, AFPVersionUnknown} }; *************** *** 216,221 **** --- 219,229 ---- private DumpBuf(), clockstart(), clockend(); + private struct sig { + byte filler[8]; + struct timeval s_time; + } sig; + #ifdef LOGIN_AUTH_PROG extern char *srvrname; /* NBP registered name of server */ extern char *login_auth_prog; /* name of authorization program */ *************** *** 254,259 **** --- 262,271 ---- #ifdef STAT_CACHE OSStatInit(); /* init stat cache */ #endif STAT_CACHE + + /* init server signature */ + bzero((char *)&sig, sizeof(struct sig)); + gettimeofday(&sig.s_time, NULL); } /* *************** *** 968,974 **** fprintf(dbg, "\tMsgTyp: %04x\t", smrp.msgr_typ); fprintf(dbg, "(%s)\n", (smrp.msgr_typ == 0) ? "Login" : "Server"); fprintf(dbg, "\tMsgBMp: %04x\n", smrp.msgr_bitmap); ! dbg_print_name("\tMsgStr:", smrp.msgr_data); fflush(dbg); } #endif /* DEBUG_AFP_CMD */ --- 980,986 ---- fprintf(dbg, "\tMsgTyp: %04x\t", smrp.msgr_typ); fprintf(dbg, "(%s)\n", (smrp.msgr_typ == 0) ? "Login" : "Server"); fprintf(dbg, "\tMsgBMp: %04x\n", smrp.msgr_bitmap); ! fprintf(dbg, "\tMsgStr: %s\n", smrp.msgr_data); fflush(dbg); } #endif /* DEBUG_AFP_CMD */ *************** *** 1035,1040 **** --- 1047,1055 ---- } #endif + #define MAXNADSIZ 8 /* tag #2, IP addr & port */ + #define NUMNAD 5 /* no more than 5 IP addr/host */ + int GetSrvrInfo(r,sname,icon,iconsize) byte *r; *************** *** 1042,1068 **** byte icon[]; int iconsize; { int i,len; extern int nopwdsave; GetSrvrInfoReplyPkt sr; byte avobuf[AFPVERSZ],uamobuf[AFPUAMSZ]; ! OPTRType avo,uamo,vicono; ! strcpy(sr.sr_machtype,afpmtyp); ! cpyc2pstr(sr.sr_servername,sname); ! /* set server capabilities */ sr.sr_flags = SupportsFPCopyFile; #ifdef DISTRIB_PASSWDS sr.sr_flags |= SupportsChgPwd; #endif DISTRIB_PASSWDS sr.sr_flags |= SupportsServerMsgs; if (nopwdsave) sr.sr_flags |= DontAllowSavePwd; vicono.optr_loc = icon; vicono.optr_len = iconsize; sr.sr_vicono = (char *) &vicono; IniIndStr(avobuf); for (i = 0; afpversions[i].version_name != NULL; i++) AddIndStr(afpversions[i].version_name, avobuf); --- 1057,1109 ---- byte icon[]; int iconsize; { + byte *q; int i,len; extern int nopwdsave; GetSrvrInfoReplyPkt sr; + OPTRType avo,uamo,vicono,sigo,nado; byte avobuf[AFPVERSZ],uamobuf[AFPUAMSZ]; ! byte nadbuf[MAXNADSIZ*NUMNAD+1]; ! extern u_short asip_port; ! extern u_int asip_addr; ! extern int asip_enable; ! struct hostent *he; ! char hostname[128]; ! /* ! * set server capabilities ! * ! */ sr.sr_flags = SupportsFPCopyFile; #ifdef DISTRIB_PASSWDS sr.sr_flags |= SupportsChgPwd; #endif DISTRIB_PASSWDS sr.sr_flags |= SupportsServerMsgs; + sr.sr_flags |= SupportsServerSig; + if (asip_enable) + sr.sr_flags |= SupportsTCPIP; if (nopwdsave) sr.sr_flags |= DontAllowSavePwd; + /* + * set Server Name & Machine Type + * + */ + strcpy(sr.sr_machtype,afpmtyp); + cpyc2pstr(sr.sr_servername,sname); + + /* + * set Volume Icon & Mask + * + */ vicono.optr_loc = icon; vicono.optr_len = iconsize; sr.sr_vicono = (char *) &vicono; + /* + * set AFP Versions + * + */ IniIndStr(avobuf); for (i = 0; afpversions[i].version_name != NULL; i++) AddIndStr(afpversions[i].version_name, avobuf); *************** *** 1070,1075 **** --- 1111,1120 ---- avo.optr_loc = avobuf; sr.sr_avo = (byte *) &avo; + /* + * set UAMs + * + */ IniIndStr(uamobuf); for (i=0 ; i < numuam; i++) AddIndStr(afpuams[i].uamname, uamobuf); *************** *** 1077,1082 **** --- 1122,1191 ---- uamo.optr_loc = uamobuf; sr.sr_uamo = (byte *) &uamo; + /* + * set server signature + * + */ + sigo.optr_len = 16; + sigo.optr_loc = (byte *)&sig; + sr.sr_sigo = (byte *)&sigo; + + /* + * set network address(es) + * use single bound address (-B ) + * or all known addresses for this machine + * + */ + q = nadbuf+1; + nadbuf[0] = 0; + if (asip_enable) { + if (asip_addr) { + nadbuf[0] = 1; + q[2] = (asip_addr >> 24) & 0xff; + q[3] = (asip_addr >> 16) & 0xff; + q[4] = (asip_addr >> 8) & 0xff; + q[5] = (asip_addr & 0xff); + if (asip_port == ASIP_PORT) { + q[0] = 0x06; /* len */ + q[1] = 0x01; /* tag */ + q += 6; + } else { + q[0] = 0x08; /* len */ + q[1] = 0x02; /* tag */ + q[6] = asip_port >> 8; + q[7] = asip_port & 0xff; + q += 8; + } + } else { /* list all known addresses */ + if (gethostname(hostname, sizeof(hostname)) == 0) { + if ((he = gethostbyname(hostname)) != NULL) { + for (i = 0; he->h_addr_list[i] && i < NUMNAD; i++) { + bcopy(he->h_addr_list[i], q+2, 4); /* copy IP */ + if (asip_port == ASIP_PORT) { + q[0] = 0x06; /* len */ + q[1] = 0x01; /* tag */ + q += 6; + } else { + q[0] = 0x08; /* len */ + q[1] = 0x02; /* tag */ + q[6] = asip_port >> 8; + q[7] = asip_port & 0xff; + q += 8; + } + } + nadbuf[0] = i; + } + } + } + } + nado.optr_len = q-nadbuf; + nado.optr_loc = nadbuf; + sr.sr_naddro = (byte *)&nado; + + /* + * pack data for sending + * + */ len = htonPackX(ProtoSRP,(byte *) &sr,r); #ifdef DEBUG_AFP_CMD *************** *** 1389,1395 **** int i; byte *q = r; u_short srvrflags; ! short machoff, afpoff, uamoff, vicnoff; void dbg_print_name(); void dbg_print_sflg(); void dbg_print_icon(); --- 1498,1505 ---- int i; byte *q = r; u_short srvrflags; ! short machoff, afpoff, uamoff; ! short vicnoff, sigoff, nadoff; void dbg_print_name(); void dbg_print_sflg(); void dbg_print_icon(); *************** *** 1402,1410 **** fprintf(dbg, "\tUAMOff: %d\n", uamoff); vicnoff = get2(q); q += 2; fprintf(dbg, "\tICNOff: %d\n", vicnoff); ! fprintf(dbg, "\tVolFlg: %04x\t", (srvrflags = get2(q))); q += 2; dbg_print_sflg(srvrflags); dbg_print_name("\tSrvrNm:", q); if (machoff != 0) dbg_print_name("\tMchTyp:", r+machoff); if (afpoff != 0) { --- 1512,1528 ---- fprintf(dbg, "\tUAMOff: %d\n", uamoff); vicnoff = get2(q); q += 2; fprintf(dbg, "\tICNOff: %d\n", vicnoff); ! srvrflags = get2(q); q += 2; ! fprintf(dbg, "\tVolFlg: %04x\t", srvrflags); dbg_print_sflg(srvrflags); dbg_print_name("\tSrvrNm:", q); + q += ((*q)+1); + if ((u_long)q & 0x01) + q++; /* even */ + sigoff = get2(q); q += 2; + fprintf(dbg, "\tSIGOff: %d\n", sigoff); + nadoff = get2(q); q += 2; + fprintf(dbg, "\tNADOff: %d\n", nadoff); if (machoff != 0) dbg_print_name("\tMchTyp:", r+machoff); if (afpoff != 0) { *************** *** 1412,1418 **** fprintf(dbg, "\tVerCnt: %d\n", (int)(*q)); for (i = *q++; i > 0; i--) { dbg_print_name("\tAFPVer:", q); ! q += ((*q) + 1); } } else fprintf(dbg, "\t\n"); --- 1530,1536 ---- fprintf(dbg, "\tVerCnt: %d\n", (int)(*q)); for (i = *q++; i > 0; i--) { dbg_print_name("\tAFPVer:", q); ! q += ((*q) + 1); } } else fprintf(dbg, "\t\n"); *************** *** 1431,1436 **** --- 1549,1588 ---- fprintf(dbg, "\n"); } else fprintf(dbg, "\t\n"); + if (sigoff != 0) { + q = r + sigoff; + fprintf(dbg, "\tSrvSIG: "); + for (i = 0; i < 16; i++) + fprintf(dbg, "%02x ", *(q+i)); + fprintf(dbg, "\n"); + } else + fprintf(dbg, "\t\n"); + if (nadoff != 0) { + q = r + nadoff; + fprintf(dbg, "\tNADCnt: %d\n", (int)(*q)); + for (i = *q++; i > 0; i--) { + fprintf(dbg, "\tAFPNAD: len %d tag %d ", q[0], q[1]); + switch (q[1]) { + case 0x01: + fprintf(dbg, "IP %d.%d.%d.%d\n", + q[2], q[3], q[4], q[5]); + break; + case 0x02: + fprintf(dbg, "IP %d.%d.%d.%d Port %d\n", + q[2], q[3], q[4], q[5], (q[6] << 8) | q[7]); + break; + case 0x03: + fprintf(dbg, "DDP net %d.%d node %d skt %d\n", + q[2], q[3], q[4], q[5]); + break; + default: + fprintf(dbg, "\n"); + break; + } + q += q[0]; + } + } else + fprintf(dbg, "\t\n"); return; } *************** *** 1475,1485 **** bmap &= ~(0x0001 << i); switch (i) { case 0: ! fprintf(dbg, "SuppCopyFile"); j++; break; case 1: ! fprintf(dbg, "SuppChngPass"); j++; break; case 2: --- 1627,1637 ---- bmap &= ~(0x0001 << i); switch (i) { case 0: ! fprintf(dbg, "CopyFile"); j++; break; case 1: ! fprintf(dbg, "ChngPass"); j++; break; case 2: *************** *** 1487,1497 **** j++; break; case 3: ! fprintf(dbg, "SuppSrvrMesg"); j++; break; case 15: ! fprintf(dbg, "SuppMGetReqs"); j++; break; default: --- 1639,1661 ---- j++; break; case 3: ! fprintf(dbg, "SrvrMesg"); ! j++; ! break; ! case 4: ! fprintf(dbg, "SrvrSig"); ! j++; ! break; ! case 5: ! fprintf(dbg, "TCP/IP"); ! j++; ! break; ! case 6: ! fprintf(dbg, "SrvrNotf"); j++; break; case 15: ! fprintf(dbg, "MGetReqs"); j++; break; default: *** applications/aufs/aufs.c.orig Wed Sep 25 00:10:19 1996 --- applications/aufs/aufs.c Fri Jul 11 19:29:43 1997 *************** *** 91,96 **** --- 91,100 ---- export u_char *srvrtype = (u_char *)AFSTYPE; /* NBP registered type */ export char *messagefile = NULL; /* AFP2.1 GetSrvrMsg srvr msg filename */ export char *motdfile = NULL; /* AFP2.1 GetSrvrMsg login msg filename */ + export char *dsiTCPIPFilter = NULL; /* AFP2.2 AppleShareIP address filter */ + export u_int asip_addr = INADDR_ANY; /* AFP2.2 AppleShare over TCP/IP */ + export u_short asip_port = ASIP_PORT; /* AFP2.2 AppleShare TCP/IP port */ + export int asip_enable = FALSE; /* AFP2.2 AppleShare TCP/IP default off */ private char *sysvolfile = NULL; /* system afpvols file */ private char *passwdlookaside = NULL; /* local password file??? */ *************** *** 240,245 **** --- 244,252 ---- fprintf(stderr,"\t-V VolsFile for server wide afp volumes\n"); fprintf(stderr,"\t-G to set guest id for logins\n"); fprintf(stderr,"\t-P LookAsidePasswordFile for scrambled transactions\n"); + fprintf(stderr,"\t-T enable AFP connections via TCP/IP (default addr)\n"); + fprintf(stderr,"\t-B enable AFP over TCP/IP & set address\n"); + fprintf(stderr,"\t-f set the AFP over TCP-IP address filter\n"); fprintf(stderr,"\t-U to allow sessions\n"); fprintf(stderr,"\t-m|M specifies login or server message file\n"); #ifndef STAT_CACHE *************** *** 297,307 **** char **argv; { int c; u_char *parsename(); extern char *optarg; extern int optind; extern boolean dochecksum; ! static char optlist[64] = "a:d:D:n:N:t:kpsuV:U:G:P:c:l:z:S:R:M:m:"; #ifdef ISO_TRANSLATE void cISO2Mac(); #endif ISO_TRANSLATE --- 304,315 ---- char **argv; { int c; + char *p; u_char *parsename(); extern char *optarg; extern int optind; extern boolean dochecksum; ! static char optlist[100] = "a:B:d:f:D:n:N:t:kpsTuV:U:G:P:c:l:z:S:R:M:m:"; #ifdef ISO_TRANSLATE void cISO2Mac(); #endif ISO_TRANSLATE *************** *** 388,393 **** --- 396,417 ---- if (!SetPktTrace(optarg)) usage(argv[0]); break; + case 'f': /* AppleShareIP IP address filter */ + dsiTCPIPFilter = optarg; + break; + case 'B': /* Bind AppleShare TCP/IP address */ + if ((p = (char *)index(optarg, ':')) != NULL) { + asip_port = atoi(p+1); + *p = '\0'; + } + if ((asip_addr = (u_int)ntohl(inet_addr(optarg))) == -1) + asip_addr = INADDR_ANY; + if (p != NULL) + *p = ':'; + /* fall through */ + case 'T': /* Enable AppleShare TCP/IP */ + asip_enable = TRUE; + break; case 'V': /* system afpvols file */ sysvolfile = optarg; break; *************** *** 688,693 **** --- 712,722 ---- if ((ctp_stack = (int *)malloc(sizeof(int)*maxsess)) == NULL) { logit(0,"couldn't malloc stack for pid recording, fatal!"); } + if (asip_enable) + if (asip_addr != INADDR_ANY) + logit(0,"AFP over TCP/IP enabled (IP %08x Port %d)",asip_addr,asip_port); + else + logit(0,"AFP over TCP/IP enabled (IP INADDR_ANY Port %d)", asip_port); #ifdef LWSRV_AUFS_SECURITY if (userlogindir != NULL) { /* budd... */ logit(0,"Aufs: user login database in %s", userlogindir); *************** *** 725,731 **** if (n_rrpkts < atpMaxNum) logit(0,"remote limited to %d packet%s in a response", n_rrpkts, n_rrpkts > 1 ? "s" : ""); ! SPGetParms(&mcs, &qs); if (DBDEB) printf("Command buffer size is %d, Quantum size is %d\n", mcs, qs); buf = (byte *)malloc(mcs); --- 754,760 ---- if (n_rrpkts < atpMaxNum) logit(0,"remote limited to %d packet%s in a response", n_rrpkts, n_rrpkts > 1 ? "s" : ""); ! dsiGetParms(&mcs, &qs); if (DBDEB) printf("Command buffer size is %d, Quantum size is %d\n", mcs, qs); buf = (byte *)malloc(mcs); *************** *** 783,798 **** PrtSrvrInfo(srvinfo,srvinfolen); /* Init asp */ ! err = SPInit(&addr,srvinfo,srvinfolen,&slsref); if (err != noErr) { ! logit(0,"SPInit failed with code %d, fatal",err); exit(0); } logit(0,"Aufs Starting (%s)",srvrname); if (sysvolfile) logit(0,"System vols in '%s'",sysvolfile); ! logit(0,"SPInit Completed. Waiting for connection..."); #ifndef NOSHUTDOWNCODE # ifndef NOPGRP --- 812,827 ---- PrtSrvrInfo(srvinfo,srvinfolen); /* Init asp */ ! err = dsiInit(&addr,srvinfo,srvinfolen,&slsref); if (err != noErr) { ! logit(0,"dsiInit failed with code %d, fatal",err); exit(0); } logit(0,"Aufs Starting (%s)",srvrname); if (sysvolfile) logit(0,"System vols in '%s'",sysvolfile); ! logit(0,"dsiInit Completed. Waiting for connection..."); #ifndef NOSHUTDOWNCODE # ifndef NOPGRP *************** *** 819,825 **** do { pid = -1; /* make sure zero at start */ ! SPGetSession(slsref,&cno,&comp); if (comp > 0) logit(0,"Waiting for session %d to activate", cno); /* won't wait if we set comp above */ --- 848,854 ---- do { pid = -1; /* make sure zero at start */ ! dsiGetSession(slsref,&cno,&comp); if (comp > 0) logit(0,"Waiting for session %d to activate", cno); /* won't wait if we set comp above */ *************** *** 848,855 **** sesscount++; logit(0,"New session %d started on server socket %d, count %d", cno,slsref,sesscount); ! if ((err = SPGetNetworkInfo(cno, &addr)) != noErr) { ! logit(0,"Get Network info failed with error %d", err); } else { #ifdef AUTHENTICATE err = (authenticate(ntohs(addr.net), addr.node)) ? noErr : ~noErr; --- 877,889 ---- sesscount++; logit(0,"New session %d started on server socket %d, count %d", cno,slsref,sesscount); ! if ((err = dsiGetNetworkInfo(cno, &addr)) != noErr) { ! if (err > 0) { /* AppleShareIP session */ ! logit(0,"Session %d from [IP addr %d.%d.%d.%d, port %d]", ! cno, addr.net>>8, addr.net&0xff, addr.node, addr.skt, err); ! err = noErr; ! } else ! logit(0,"Get Network info failed with error %d", err); } else { #ifdef AUTHENTICATE err = (authenticate(ntohs(addr.net), addr.node)) ? noErr : ~noErr; *************** *** 864,870 **** } #ifdef AUTHENTICATE if(err != noErr) { ! SPCloseSession(cno, 1, 1, &comp2); continue; } #endif AUTHENTICATE --- 898,904 ---- } #ifdef AUTHENTICATE if(err != noErr) { ! dsiCloseSession(cno, 1, 1, &comp2); continue; } #endif AUTHENTICATE *************** *** 889,898 **** # endif NOSHUTDOWNCODE; #endif NOSIGMASK /* fork on connection - only tickle from parent */ ! if ((pid = SPFork(cno, TRUE, FALSE)) < 0) { ! logit(0,"SPFork failed on session %d, last system error %d",cno, errno); /* try to close, but don't worry too much */ ! SPCloseSession(cno, 1, 1, &comp2); #ifdef NOSIGMASK sigrelse(SIGCHLD); sigrelse(SIGHUP); --- 923,932 ---- # endif NOSHUTDOWNCODE; #endif NOSIGMASK /* fork on connection - only tickle from parent */ ! if ((pid = dsiFork(cno, TRUE, FALSE)) < 0) { ! logit(0,"dsiFork failed on session %d, last system error %d",cno,errno); /* try to close, but don't worry too much */ ! dsiCloseSession(cno, 1, 1, &comp2); #ifdef NOSIGMASK sigrelse(SIGCHLD); sigrelse(SIGHUP); *************** *** 905,912 **** #endif NOSIGMASK continue; } if (pid) { - SPTickleUserRoutine(cno, timedout, pid); logit(0,"pid %d starting for session %d",pid, cno); addinferior(cno, pid); /* addinferior scans (phew) */ } else { --- 939,946 ---- #endif NOSIGMASK continue; } + dsiTickleUserRoutine(cno, timedout, pid); if (pid) { logit(0,"pid %d starting for session %d",pid, cno); addinferior(cno, pid); /* addinferior scans (phew) */ } else { *************** *** 997,1003 **** umask(0); /* file creates have explict modes */ for (;;) { #ifndef TREL_TIMEOUT ! SPGetRequest(cno,buf,mcs,&reqref,&type,&rlen,&comp); while (comp > 0) { abSleep(sectotick(60),TRUE); #ifdef AUFS_IDLE_TIMEOUT --- 1031,1037 ---- umask(0); /* file creates have explict modes */ for (;;) { #ifndef TREL_TIMEOUT ! dsiGetRequest(cno,buf,mcs,&reqref,&type,&rlen,&comp); while (comp > 0) { abSleep(sectotick(60),TRUE); #ifdef AUFS_IDLE_TIMEOUT *************** *** 1016,1022 **** } if (comp1 <= 0) { ! SPGetRequest(cno,buf1,mcs,&reqref1,&type1,&rlen1,&comp1); while (comp1 > 0) { abSleep(sectotick(60),TRUE); #ifdef AUFS_IDLE_TIMEOUT --- 1050,1056 ---- } if (comp1 <= 0) { ! dsiGetRequest(cno,buf1,mcs,&reqref1,&type1,&rlen1,&comp1); while (comp1 > 0) { abSleep(sectotick(60),TRUE); #ifdef AUFS_IDLE_TIMEOUT *************** *** 1034,1043 **** } #ifndef TREL_TIMEOUT if (comp < 0) { ! logit(0,"SPGetRequest failed %d",comp); #else TREL_TIMEOUT if (comp1 < 0) { ! logit(0,"SPGetRequest failed %d",comp1); #endif TREL_TIMEOUT continue; } --- 1068,1077 ---- } #ifndef TREL_TIMEOUT if (comp < 0) { ! logit(0,"dsiGetRequest failed %d",comp); #else TREL_TIMEOUT if (comp1 < 0) { ! logit(0,"dsiGetRequest failed %d",comp1); #endif TREL_TIMEOUT continue; } *************** *** 1079,1108 **** } #ifndef TREL_TIMEOUT if (type == aspWrite) ! SPWrtReply(cno,reqref,(dword) err,rspbuf,rsplen,&comp); #else TREL_TIMEOUT if (type1 == aspWrite) ! SPWrtReply(cno,reqref1,(dword) err,rspbuf1,rsplen1,&comp1); #endif TREL_TIMEOUT else #ifndef TREL_TIMEOUT ! SPCmdReply(cno,reqref,(dword) err,rspbuf,rsplen,&comp); while (comp > 0) { abSleep(sectotick(60),TRUE); } if (DBSRV) printf("done\n"); #else TREL_TIMEOUT ! SPCmdReply(cno,reqref1,(dword) err,rspbuf1,rsplen1,&comp1); #endif TREL_TIMEOUT break; case aspCloseSession: logit(0,"Closing ASP Session..."); #ifndef TREL_TIMEOUT ! SPCloseSession(cno,10,3,&comp); /* 5 times, .75 seconds */ while (comp > 0) #else TREL_TIMEOUT ! SPCloseSession(cno,10,3,&comp1); /* 5 times, .75 seconds */ while (comp1 > 0) #endif TREL_TIMEOUT abSleep(1, TRUE); --- 1113,1142 ---- } #ifndef TREL_TIMEOUT if (type == aspWrite) ! dsiWrtReply(cno,reqref,(dword) err,rspbuf,rsplen,&comp); #else TREL_TIMEOUT if (type1 == aspWrite) ! dsiWrtReply(cno,reqref1,(dword) err,rspbuf1,rsplen1,&comp1); #endif TREL_TIMEOUT else #ifndef TREL_TIMEOUT ! dsiCmdReply(cno,reqref,(dword) err,rspbuf,rsplen,&comp); while (comp > 0) { abSleep(sectotick(60),TRUE); } if (DBSRV) printf("done\n"); #else TREL_TIMEOUT ! dsiCmdReply(cno,reqref1,(dword) err,rspbuf1,rsplen1,&comp1); #endif TREL_TIMEOUT break; case aspCloseSession: logit(0,"Closing ASP Session..."); #ifndef TREL_TIMEOUT ! dsiCloseSession(cno,10,3,&comp); /* 5 times, .75 seconds */ while (comp > 0) #else TREL_TIMEOUT ! dsiCloseSession(cno,10,3,&comp1); /* 5 times, .75 seconds */ while (comp1 > 0) #endif TREL_TIMEOUT abSleep(1, TRUE); *************** *** 1133,1139 **** #endif NOSHUTDOWNCODE; #ifdef TREL_TIMEOUT } else { /* comp2 */ ! SPGetRequest(cno,buf2,mcs,&reqref2,&type2,&rlen2,&comp2); while (comp2 > 0) { abSleep(sectotick(60),TRUE); #ifdef AUFS_IDLE_TIMEOUT --- 1167,1173 ---- #endif NOSHUTDOWNCODE; #ifdef TREL_TIMEOUT } else { /* comp2 */ ! dsiGetRequest(cno,buf2,mcs,&reqref2,&type2,&rlen2,&comp2); while (comp2 > 0) { abSleep(sectotick(60),TRUE); #ifdef AUFS_IDLE_TIMEOUT *************** *** 1149,1155 **** return; } if (comp2 < 0) { ! logit(0,"SPGetRequest failed %d",comp2); continue; } if (rlen2 == 0) --- 1183,1189 ---- return; } if (comp2 < 0) { ! logit(0,"dsiGetRequest failed %d",comp2); continue; } if (rlen2 == 0) *************** *** 1173,1185 **** fflush(stdout); /* force out */ } if (type2 == aspWrite) ! SPWrtReply(cno,reqref2,(dword) err,rspbuf2,rsplen2,&comp2); else ! SPCmdReply(cno,reqref2,(dword) err,rspbuf2,rsplen2,&comp2); break; case aspCloseSession: logit(0,"Closing ASP Session..."); ! SPCloseSession(cno,10,3,&comp2); /* 5 times, .75 seconds */ while (comp2 > 0) abSleep(1, TRUE); #ifndef NOSHUTDOWNCODE --- 1207,1219 ---- fflush(stdout); /* force out */ } if (type2 == aspWrite) ! dsiWrtReply(cno,reqref2,(dword) err,rspbuf2,rsplen2,&comp2); else ! dsiCmdReply(cno,reqref2,(dword) err,rspbuf2,rsplen2,&comp2); break; case aspCloseSession: logit(0,"Closing ASP Session..."); ! dsiCloseSession(cno,10,3,&comp2); /* 5 times, .75 seconds */ while (comp2 > 0) abSleep(1, TRUE); #ifndef NOSHUTDOWNCODE *************** *** 1300,1308 **** logit(0,"process %d, session %d was suspended! gads what is happening?", cp->pid, srn); } else if (WIFSIGNALED(cp->status)) { ! SPAttention(srn, AFPSHUTDOWNNOW, 1, -1, &comp); while (comp > 0) {abSleep(30, TRUE);} /* ignore error */ ! SPCloseSession(srn, 3, 2, &comp); /* try 3 times every .5 seconds */ while (comp > 0) { abSleep(30, TRUE); } /* close down if we can */ logit(0,"process %d, session %d was terminated on signal %d", cp->pid, srn, W_TERMSIG(cp->status)); --- 1334,1342 ---- logit(0,"process %d, session %d was suspended! gads what is happening?", cp->pid, srn); } else if (WIFSIGNALED(cp->status)) { ! dsiAttention(srn, AFPSHUTDOWNNOW, 1, -1, &comp); while (comp > 0) {abSleep(30, TRUE);} /* ignore error */ ! dsiCloseSession(srn, 3, 2, &comp); /* try 3 times every .5 seconds */ while (comp > 0) { abSleep(30, TRUE); } /* close down if we can */ logit(0,"process %d, session %d was terminated on signal %d", cp->pid, srn, W_TERMSIG(cp->status)); *************** *** 1321,1327 **** logit(0,"process %d, session %d terminated with exit code %d", cp->pid, srn, W_RETCODE(cp->status)); } ! SPShutdown(srn); nomoresessions = FALSE; /* if this was set, unset now */ #ifdef DORUSAGE logit(0,"%d messages out, %d in, CPU %.2f user %.2f system", --- 1355,1361 ---- logit(0,"process %d, session %d terminated with exit code %d", cp->pid, srn, W_RETCODE(cp->status)); } ! dsiShutdown(srn); nomoresessions = FALSE; /* if this was set, unset now */ #ifdef DORUSAGE logit(0,"%d messages out, %d in, CPU %.2f user %.2f system", *************** *** 1385,1391 **** /* assume sigchild interlocked here */ if (ctp_tab[srn].state & CP_RUNNING) ctp_tab[srn].state |= CP_TIMEDOUT; ! SPShutdown(srn); /* ignore errors */ kill(pid, SIGHUP); /* hangup inferior */ } --- 1419,1425 ---- /* assume sigchild interlocked here */ if (ctp_tab[srn].state & CP_RUNNING) ctp_tab[srn].state |= CP_TIMEDOUT; ! dsiShutdown(srn); /* ignore errors */ kill(pid, SIGHUP); /* hangup inferior */ } *************** *** 1399,1408 **** /* The following shouldn't really do anything since remote should be gone */ /* be in case it really isn't, let's go through this rigamorle */ /* Tell remote we are shutting down */ ! SPAttention(cno, AFPSHUTDOWNNOW, 1, -1, &comp); while (comp > 0) {abSleep(30, TRUE);} /* ignore error */ /* Try closing just in case */ ! SPCloseSession(cno, 3, 2, &comp); /* 3 times, .5 seconds */ while (comp > 0) { abSleep(30, TRUE); } /* close down if we can */ #ifdef LWSRV_AUFS_SECURITY clearuserlogin(); /* gtw: delete auth-file entry for dead users */ --- 1433,1442 ---- /* The following shouldn't really do anything since remote should be gone */ /* be in case it really isn't, let's go through this rigamorle */ /* Tell remote we are shutting down */ ! dsiAttention(cno, AFPSHUTDOWNNOW, 1, -1, &comp); while (comp > 0) {abSleep(30, TRUE);} /* ignore error */ /* Try closing just in case */ ! dsiCloseSession(cno, 3, 2, &comp); /* 3 times, .5 seconds */ while (comp > 0) { abSleep(30, TRUE); } /* close down if we can */ #ifdef LWSRV_AUFS_SECURITY clearuserlogin(); /* gtw: delete auth-file entry for dead users */ *************** *** 1431,1437 **** /* Tell remote we are shutting down */ if (minutes_to_shutdown % 2) { /* all odd minutes */ /* there is a potential race condition here */ ! SPAttention(cno, AFPSHUTDOWNTIME(minutes_to_shutdown), 1, -1, &comp); while (comp > 0) {abSleep(30, TRUE);} /* ignore error */ } minutes_to_shutdown--; --- 1465,1471 ---- /* Tell remote we are shutting down */ if (minutes_to_shutdown % 2) { /* all odd minutes */ /* there is a potential race condition here */ ! dsiAttention(cno, AFPSHUTDOWNTIME(minutes_to_shutdown), 1, -1, &comp); while (comp > 0) {abSleep(30, TRUE);} /* ignore error */ } minutes_to_shutdown--; *************** *** 1465,1471 **** int comp; signal(SIGURG, SIG_IGN); ! SPAttention(cno, AFPSERVERMESG, 1, -1, &comp); while (comp > 0) abSleep(30, TRUE); signal(SIGURG, msgavail); --- 1499,1505 ---- int comp; signal(SIGURG, SIG_IGN); ! dsiAttention(cno, AFPSERVERMESG, 1, -1, &comp); while (comp > 0) abSleep(30, TRUE); signal(SIGURG, msgavail); *************** *** 1893,1899 **** if (cmp == 0 && *buf != 17) { /* periodic GetVolParms AFP call */ if (sentshutdown) { logit(0, "Session %d: Aborting Idle Timeout", cno); ! SPAttention(cno, AFPSHUTDOWNCANCEL, 1, -1, &comp); while (comp > 0) { abSleep(30, TRUE); } /* ignore error */ sentshutdown = 0; } --- 1927,1933 ---- if (cmp == 0 && *buf != 17) { /* periodic GetVolParms AFP call */ if (sentshutdown) { logit(0, "Session %d: Aborting Idle Timeout", cno); ! dsiAttention(cno, AFPSHUTDOWNCANCEL, 1, -1, &comp); while (comp > 0) { abSleep(30, TRUE); } /* ignore error */ sentshutdown = 0; } *************** *** 1922,1937 **** case 12: /* shutdown in 3 min */ case 24: /* shutdown in 1 min */ logit(0, "Session %d: sending %d minute idle timeout warning",cno,5-i/6); ! SPAttention(cno, AFPSHUTDOWNTIME(5-i/6), 1, -1, &comp); while (comp > 0) { abSleep(30, TRUE); } /* ignore error */ sentshutdown++; return; break; case 30: /* shutdown now */ logit(0, "Session %d: Idle Timeout Shutdown", cno); ! SPAttention(cno, AFPSHUTDOWNNOW, 1, -1, &comp); while (comp > 0) { abSleep(30, TRUE); } /* ignore error */ ! SPCloseSession(cno, 3, 2, &comp); /* 3 times, .5 seconds */ while (comp > 0) { abSleep(30, TRUE); } /* close down if we can */ #ifdef LWSRV_AUFS_SECURITY clearuserlogin(); /* gtw: delete auth-file entry for dead users */ --- 1956,1971 ---- case 12: /* shutdown in 3 min */ case 24: /* shutdown in 1 min */ logit(0, "Session %d: sending %d minute idle timeout warning",cno,5-i/6); ! dsiAttention(cno, AFPSHUTDOWNTIME(5-i/6), 1, -1, &comp); while (comp > 0) { abSleep(30, TRUE); } /* ignore error */ sentshutdown++; return; break; case 30: /* shutdown now */ logit(0, "Session %d: Idle Timeout Shutdown", cno); ! dsiAttention(cno, AFPSHUTDOWNNOW, 1, -1, &comp); while (comp > 0) { abSleep(30, TRUE); } /* ignore error */ ! dsiCloseSession(cno, 3, 2, &comp); /* 3 times, .5 seconds */ while (comp > 0) { abSleep(30, TRUE); } /* close down if we can */ #ifdef LWSRV_AUFS_SECURITY clearuserlogin(); /* gtw: delete auth-file entry for dead users */ *** applications/aufs/Makefile.m4.orig Wed Sep 25 00:09:57 1996 --- applications/aufs/Makefile.m4 Mon Jul 7 02:03:26 1997 *************** *** 48,59 **** afpmisc.c afpserver.c aufsicon.c abmisc2.c \ afpdt.c afpdid.c afposenum.c afpavl.c \ afposfi.c afpgc.c afppasswd.c afposlock.c aufsv.c \ ! afpudb.c afposncs.c afpspd.c afpfid.c OBJS=afpos.o afpvols.o afpfile.o \ afpmisc.o afpserver.o aufsicon.o abmisc2.o \ afpdt.o afpdir.o afpfork.o afpdid.o afposenum.o afpavl.o \ afposfi.o afpgc.o afppasswd.o aufsv.o \ ! afpudb.o afposncs.o afpspd.o afpfid.o SYMLINKS=att_getopt.c all: aufs sizeserver afpidsrvr afpidlist afpidtool --- 48,59 ---- afpmisc.c afpserver.c aufsicon.c abmisc2.c \ afpdt.c afpdid.c afposenum.c afpavl.c \ afposfi.c afpgc.c afppasswd.c afposlock.c aufsv.c \ ! afpudb.c afposncs.c afpspd.c afpfid.c afpdsi.c OBJS=afpos.o afpvols.o afpfile.o \ afpmisc.o afpserver.o aufsicon.o abmisc2.o \ afpdt.o afpdir.o afpfork.o afpdid.o afposenum.o afpavl.o \ afposfi.o afpgc.o afppasswd.o aufsv.o \ ! afpudb.o afposncs.o afpspd.o afpfid.o afpdsi.o SYMLINKS=att_getopt.c all: aufs sizeserver afpidsrvr afpidlist afpidtool *************** *** 189,191 **** --- 189,193 ---- afppasswd.o: afppasswd.c $I/netat/sysvcompat.h afppasswd.h afposncs.o: afposncs.c $I/netat/appletalk.h $I/netat/afp.h \ afposncs.h afps.h + afpdsi.o: afpdsi.c $I/netat/appletalk.h ../../lib/cap/abasp.h \ + afpdsi.h *** lib/afp/afppacks.c.orig Wed Sep 25 00:10:07 1996 --- lib/afp/afppacks.c Mon Mar 3 17:34:40 1997 *************** *** 615,620 **** --- 615,622 ---- PAKB(GVPRPPtr,P_DWRD,gvpr_free,VP_FREE), /* free bytes */ PAKB(GVPRPPtr,P_DWRD,gvpr_size,VP_SIZE), /* size in bytes */ PKSB(GVPRPPtr,P_OSTR,gvpr_name,VP_NAME), /* name of volume */ + PKSB(GVPRPPtr,P_BYTS,gvpr_efree,VP_EFREE), /* extended free bytes */ + PKSB(GVPRPPtr,P_BYTS,gvpr_esize,VP_ESIZE), /* extended total bytes */ PACKEND() }; *************** *** 663,668 **** --- 665,673 ---- PACK(GSIRPPtr, P_OPTR, sr_vicono), PACK(GSIRPPtr, P_WORD, sr_flags), PAKS(GSIRPPtr, P_PATH, sr_servername), + PACKEVEN(), + PACK(GSIRPPtr, P_OPTR, sr_sigo), + PACK(GSIRPPtr, P_OPTR, sr_naddro), PACKEND() }; *** lib/cap/abasp.c.orig Thu Mar 14 13:47:51 1991 --- lib/cap/abasp.c Fri Jul 11 18:20:13 1997 *************** *** 18,25 **** * Aug 4, 1986 CCKim Verified: level 0 */ - /* PATCH: Moy@Berkeley/abasp.c.diff, djh@munnari.OZ.AU, 17/11/90 */ - #include #include #include --- 18,23 ---- *************** *** 61,78 **** private void start_client_aspskt(); private void shutdown_aspskt(); ! private ASPQE *create_aq(); private ASPQE *get_aq(); - private void delete_aq(); private boolean match_aspwe(); private ASPQE *find_aspawe(); private void startasptickle(); ! private void stopasptickle(); private void ttimeout(); private void start_ttimer(); private void reset_ttimer(); ! private void stop_ttimer(); int SPFork(); OSErr SPShutdown(); --- 59,76 ---- private void start_client_aspskt(); private void shutdown_aspskt(); ! void delete_aq(); ! ASPQE *create_aq(); private ASPQE *get_aq(); private boolean match_aspwe(); private ASPQE *find_aspawe(); private void startasptickle(); ! void stopasptickle(); private void ttimeout(); private void start_ttimer(); private void reset_ttimer(); ! void stop_ttimer(); int SPFork(); OSErr SPShutdown(); *************** *** 89,98 **** #ifdef ASPPID private ASPSkt *aspskt_find_pid(); #endif - private ASPSkt *aspskt_find_active(); - private ASPSkt *aspskt_find_sessrefnum(); private OSErr aspsskt_new(); ! private ASPSSkt *aspsskt_find_slsrefnum(); private boolean aspsskt_isactive(); private void sizeof_abr_bds_and_req(); --- 87,96 ---- #ifdef ASPPID private ASPSkt *aspskt_find_pid(); #endif private OSErr aspsskt_new(); ! ASPSkt *aspskt_find_active(); ! ASPSkt *aspskt_find_sessrefnum(); ! ASPSSkt *aspsskt_find_slsrefnum(); private boolean aspsskt_isactive(); private void sizeof_abr_bds_and_req(); *************** *** 1896,1901 **** --- 1894,1900 ---- stopasptickle(as); } ATPCloseSocket(sas->addr.skt); /* close down server listener here */ + dsiTCPIPCloseSLS(); /* and the AppleShareIP SLS */ } return(pid); } *************** *** 2093,2099 **** } #endif ! private ASPSkt * aspskt_find_active(SLSRefNum) int SLSRefNum; { --- 2092,2098 ---- } #endif ! ASPSkt * aspskt_find_active(SLSRefNum) int SLSRefNum; { *************** *** 2106,2112 **** return(NULL); } ! private ASPSkt * aspskt_find_sessrefnum(srn) int srn; { --- 2105,2111 ---- return(NULL); } ! ASPSkt * aspskt_find_sessrefnum(srn) int srn; { *************** *** 2137,2143 **** } ! private ASPSSkt * aspsskt_find_slsrefnum(sls) int sls; { --- 2136,2148 ---- } ! /* ! * locate SLSRefNum structure ! * (non-private for DSI access) ! * ! */ ! ! ASPSSkt * aspsskt_find_slsrefnum(sls) int sls; { *************** *** 2212,2218 **** * stopasptickle - cancel the tickle on the specified connection * */ ! private void stopasptickle(as) ASPSkt *as; { --- 2217,2223 ---- * stopasptickle - cancel the tickle on the specified connection * */ ! void stopasptickle(as) ASPSkt *as; { *************** *** 2277,2283 **** * cancel the remote tickle timeout * */ ! private void stop_ttimer(as) ASPSkt *as; { --- 2282,2288 ---- * cancel the remote tickle timeout * */ ! void stop_ttimer(as) ASPSkt *as; { *************** *** 2291,2297 **** private ASPQE *aspqe_list; private QElemPtr aspqe_free; ! private ASPQE * create_aq(which, as) int which; ASPSkt *as; --- 2296,2302 ---- private ASPQE *aspqe_list; private QElemPtr aspqe_free; ! ASPQE * create_aq(which, as) int which; ASPSkt *as; *************** *** 2320,2326 **** return(aspqe); } ! private void delete_aq(aspqe, which, as) ASPQE *aspqe; int which; --- 2325,2331 ---- return(aspqe); } ! void delete_aq(aspqe, which, as) ASPQE *aspqe; int which; *** lib/cap/absched.c.orig Wed Sep 25 00:10:17 1996 --- lib/cap/absched.c Wed Jul 9 16:07:49 1997 *************** *** 704,709 **** --- 704,711 ---- } if (dbug.db_skd) fprintf(stderr,"%d ", rdy); + if (rdy < 0) + return(rdy); if (rdy > 0) { /* rdy should be # of set file descriptors in the masks */ /* since we only pass it the "read" bits, this loop */ *** etc/aufsIPFilter.orig Mon Jul 14 13:46:44 1997 --- etc/aufsIPFilter Mon Jul 14 13:49:11 1997 *************** *** 0 **** --- 1,26 ---- + # + # aufs/AppleShareIP Address Access Filter List + # + # NB: The filter file format is compatible with that used by the ARNS + # Remote Access package (http://www.cs.mu.OZ.AU/appletalk/atalk.html) + # + # The filter list consists of a single character mode, an IP mask and + # optional IP address. If the latter is included, the mask is applied + # to the incoming IP address and tested against the provided address. + # Otherwise the incoming IP address must be unchanged by the mask. + # + # Modes: + # + # * IP_MASK [ IP_ADDR ] permit access + # + IP_MASK [ IP_ADDR ] permit access + # - IP_MASK [ IP_ADDR ] deny access + # + # + # any mac on a specific subnet + + 255.255.255.0 192.43.207.0 + # connections from ariel + * 128.250.255.255 128.250.20.3 + # anybody on campus + + 128.243.255.255 + # nobody else + - 255.255.255.255 *** samples/ash.c.orig Wed Sep 25 00:10:10 1996 --- samples/ash.c Mon Jul 14 14:27:33 1997 *************** *** 1090,1092 **** --- 1090,1102 ---- *bp++ = '\0'; return(buf); } + + /* + * this is a dummy routine for abasp.c + * + */ + + dsiTCPIPCloseSLS() + { + return(noErr); + } *** man/AUFS.8.orig Wed Sep 25 00:09:56 1996 --- man/AUFS.8 Mon Jul 14 13:53:02 1997 *************** *** 21,26 **** --- 21,30 ---- ] [ .BI \-F " " ] [ + .BI \-B " " + ] [ + .BI \-f " " + ] [ .BI \-[i|I] " " ] [ .BI \-c " " *************** *** 45,50 **** --- 49,56 ---- ] [ .BI \-u ] [ + .BI \-T + ] [ .BI \-d " " ] [ .BI \-a " " *************** *** 57,71 **** ] .SH DESCRIPTION .I aufs ! implements a file server on a UNIX host connected ! to an AppleTalk network, for client computers on AppleTalk that support AFP. ! Specifically, it works as a file server for Macintosh computers with ! the AppleShare client code. This manual entry describes how to run the UNIX server daemon process. See AUFS(1) for information about how to use the server. .PP .I aufs ! is normally started at boot time via a command in start-cap-servers (whic is usually run from /etc/rc.local). The CAP name information server daemon .I atis --- 63,77 ---- ] .SH DESCRIPTION .I aufs ! implements a file server on a UNIX host for client computers on AppleTalk ! that support AFP, ! or Macintoshes on the internet that support AFP via TCP/IP using AppleShare ! client 3.7 or later. This manual entry describes how to run the UNIX server daemon process. See AUFS(1) for information about how to use the server. .PP .I aufs ! is normally started at boot time via a command in start-cap-servers (which is usually run from /etc/rc.local). The CAP name information server daemon .I atis *************** *** 148,153 **** --- 154,186 ---- user may over-ride these mappings by having a .afpfile (or afpfile) file in their home directory. .TP 10 + .BI \-T + enables AppleShareIP (AFP via TCP/IP) support in + .I aufs. + Note that the first + .I aufs + process defaults to the well-know port number 548. Subsequent incarnations + of + .I aufs + will require that the TCP/IP port number be specified using the \-B option. + Clients needing to connect to these servers, that are not also connected to + the same network via AppleTalk, must specify the port number in + the dialog box obtained by clicking on the Chooser "Server IP Address..." + button. The format is the same as for the \-B option, ie: 128.250.1.21:2169 + to use port number 2169 on host 128.250.1.21. + .TP 10 + .BI \-B " " + tells + .I aufs + to listen for TCP/IP connections at the specified IP address and optional + port (defaults to any available interface address and port number 548). + This option implies \-T. + .TP 10 + .BI \-f " " + specifies the pathname of a file containing yes/no permissions for client + IP numbers or subnets wishing to connect using AFP via TCP/IP. See the file + cap60/etc/aufsIPFilter for details. + .TP 10 .BI \-c " " specifies a directory where .I aufs *************** *** 341,354 **** .PP Notes and warnings pertaining to client use and file system implementation are documented in AUFS(1). - .PP - AUFS Version 3, released post 2/88, has a different .finderinfo and - desktop format than previous releases of AUFS. Old format desktop - files are automatically discarded and old format .finderinfo files are - rewritten on sight (if possible). You should consider rebuilding your - desktop if you had a volume created with AUFS Version 2 or previous to - regain the applications mappings and to ensure that all .finderinfo - files are rewritten. .SH AUTHOR AUFS was written by Bill Schilit, Computer Science Deparment and Charlie C. Kim, User Services, Columbia University. --- 374,379 ---- *** netat/afp.h.orig Wed Sep 25 00:09:55 1996 --- netat/afp.h Fri Aug 7 12:18:33 1998 *************** *** 192,207 **** /* Volume Params */ ! #define VP_ATTR 0001 /* attributes */ ! #define VP_SIG 0002 /* signature byte */ ! #define VP_CDATE 0004 /* creation date */ ! #define VP_MDATE 0010 /* modification date */ ! #define VP_BDATE 0020 /* backup date */ ! #define VP_VOLID 0040 /* volume id */ ! #define VP_FREE 0100 /* free bytes */ ! #define VP_SIZE 0200 /* size in bytes */ ! #define VP_NAME 0400 /* volume name */ ! #define VP_ALL (0777) #define VOL_VAR_DIRID 0x03 /* volume has variable dirids */ #define VOL_FIXED_DIRID 0x02 /* volume has fixed dirids */ --- 192,210 ---- /* Volume Params */ ! #define VP_ATTR 00001 /* attributes */ ! #define VP_SIG 00002 /* signature byte */ ! #define VP_CDATE 00004 /* creation date */ ! #define VP_MDATE 00010 /* modification date */ ! #define VP_BDATE 00020 /* backup date */ ! #define VP_VOLID 00040 /* volume id */ ! #define VP_FREE 00100 /* free bytes */ ! #define VP_SIZE 00200 /* size in bytes */ ! #define VP_NAME 00400 /* volume name */ ! #define VP_EFREE 01000 /* AFP2.2: extended free bytes */ ! #define VP_ESIZE 02000 /* AFP2.2: extended total bytes */ ! #define VP_ALLOC 04000 /* AFP2.2: allocation block size */ ! #define VP_ALL (07777) #define VOL_VAR_DIRID 0x03 /* volume has variable dirids */ #define VOL_FIXED_DIRID 0x02 /* volume has fixed dirids */ *************** *** 278,282 **** --- 281,287 ---- #define UIP_PRIMARY_GID 0x2 /* primary group (dword) */ #define AFSTYPE "AFPServer" /* NBP type for AFS */ + + #define ASIP_PORT 548 /* AppleShare over TCP/IP well-known port */ char *afperr(); /* in afperr.c */ *** netat/afpcmd.h.orig Wed Sep 25 00:09:56 1996 --- netat/afpcmd.h Tue Mar 4 13:22:33 1997 *************** *** 279,285 **** --- 279,290 ---- #define SupportsChgPwd 0x02 /* AFP2.0: can do change password */ #define DontAllowSavePwd 0x04 /* AFP2.1: user can't save password */ #define SupportsServerMsgs 0x08 /* AFP2.1: can send server messages */ + #define SupportsServerSig 0x10 /* AFP2.2: can supply unique signature */ + #define SupportsTCPIP 0x20 /* AFP2.2: AFP commands via TCP/IP stream */ + #define SupportsSrvrNotif 0x40 /* AFP2.2: server to client messages */ byte sr_servername[33]; /* server name */ + byte *sr_sigo; /* AFP2.2: offset to signature */ + byte *sr_naddro; /* AFP2.2: offset to network address count */ } GetSrvrInfoReplyPkt, *GSIRPPtr; typedef struct { /* FPGetSrvrParms */ *************** *** 319,324 **** --- 324,331 ---- sdword gvpr_size; /* size of volume in bytes */ sdword gvpr_free; /* free bytes on volume */ byte gvpr_name[MAXVLEN]; /* advertised name */ + byte gvpr_esize[8]; /* extended volume size */ + byte gvpr_efree[8]; /* extended bytes free */ } GetVolParmsReplyPkt, *GVPRPPtr;