#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netat/appletalk.h>
#include <netat/sysglue.h>
#include <netat/asp.h>
#include <netat/atp.h>
#include "at_rwlock.h"
#include <AppleTalk/at_proto.h>
extern int ATsocket(int protocol);
#ifndef ASP_LOCKS
int at_rwl_init(int *lock)
{
return 0;
}
void at_rwl_writelock(int *lock)
{
}
void at_rwl_writeunlock(int *lock)
{
}
void at_rwl_readlock(int *lock)
{
}
void at_rwl_readunlock(int *lock)
{
}
#endif
#define SET_ERRNO(e) errno = e
#define MSGSTR(num,str) str
#define DEFAULT_AFP_PORT 548
#define ASP_SIG_STR "M10"
#define ASPDEF_BufSize sizeof(ioc_t)
#define ASPDEF_MaxCmdSize 578
#define ASPDEF_QuantumSize 4624
#define ASPDEF_DefMaxDescr FD_SETSIZE
#define ASPDEF_MaxNumOfSLS 8
#define ASPDT_ATP_AS 1
#define ASPDT_TCP_FS 2
#define ASPFS_AFPCfgName "/etc/afpovertcp.cfg"
#define ASPFS_Reply 0x01
#define ASPFS_LastPacket 0x02
#define ASPFS_AFPWrCmdSize 12
#define ASPFS_SigSuppBit 0x10
#define ASPFS_TCPSuppBit 0x20
#define ASPFS_SigDataLen 16
#define ASPFS_DataQuantumTag 0
#define ASPFS_AttnQuantumTag 1
#define ASPFS_MaxOptLen 128
#define ASP_LINE_LEN 128
#define ASP_SESS_TIMEOUT 120
#define ASP_CONN_TIMEOUT 20
#define ASP_TICKLE_INT 30
#ifdef ASPDEBUG
static FILE *logfp = 0;
static char *newline = "\n";
#define LOG_MSG(name, param) {if (logfp) { \
fprintf(logfp, "%s(%d): ref=%d %s", name, getpid(), param, newline); \
fflush(logfp); }}
#define LOG_ERR(name) {if (logfp) { \
fprintf(logfp, "%s(%d): err=%d,errno=%d %s", name, getpid(), *SPError, errno, newline); \
fflush(logfp); }}
#else
#define LOG_MSG(name, param)
#define LOG_ERR(name)
#endif
typedef struct {
unsigned short MachineTypeOffset;
unsigned short AFPVersionsOffset;
unsigned short UAMsOffset;
unsigned short VolumeIconOffset;
unsigned short Flags;
} asp_svrinfo_t;
typedef struct {
unsigned short SigDataOffset;
unsigned short TCPDataOffset;
} asp_tcpinfo_t;
typedef struct {
unsigned char len;
unsigned char addr_tag;
unsigned char addr_value[4];
unsigned short port;
} asp_tcpaddr_t;
typedef struct {
unsigned char tag;
unsigned char len;
unsigned char val[1];
} asp_opt_t;
typedef struct {
unsigned char Flags;
unsigned char Command;
unsigned short RequestID;
int ErrorCode;
int TotalLen;
int Reserved;
} asp_fspkt_t;
static int strpfx();
static int SendCommand();
static int GetQuantumSize();
static void GetSigInfo();
static unsigned char GetTCPInfo();
static unsigned short GetListenPort();
static unsigned short DefSessionTimer = ASP_SESS_TIMEOUT;
static unsigned short DefTickleInterval = ASP_TICKLE_INT;
static at_retry_t CmdRetry = {1, 10, 1};
typedef struct {
char SessType;
char UserType;
int Quantum;
#ifdef ASP_LOCKS
at_rwlock_t RWLock;
#else
int RWLock;
#endif
asp_fspkt_t SessFSPkt;
u_short FSRangeErr;
u_short NewReqRefNum;
int NewReqType;
int NewReqLen;
char NewReqBuf[ASPDEF_MaxCmdSize];
} session_t;
static session_t *Session[ASPDEF_DefMaxDescr];
static char FSStatusBlk[sizeof(asp_fspkt_t)+ASPDEF_QuantumSize];
static int FSStatusLen = 0;
static int FSQuantumSize = 0;
static unsigned short FSRequestID = 0;
static unsigned short FSListenPort = 0;
typedef struct {
int SLSRefNum;
int IN_descr;
at_inet_t AT_addr;
unsigned short IN_port;
} listener_t;
static listener_t Listener[ASPDEF_MaxNumOfSLS];
void
initSess(sp)
session_t *sp;
{
if (sp) {
(void)memset(sp, 0, sizeof(session_t));
(void)at_rwl_init(&(sp->RWLock));
}
}
static session_t *
findSess(fd, SPError)
int fd;
int *SPError;
{
session_t *sp = (session_t *)NULL;
if ((fd < 0) || (fd >= ASPDEF_DefMaxDescr))
*SPError = ASPERR_ParamErr;
else if (!(sp = Session[fd]))
*SPError = ASPERR_NoSuchDevice;
else
*SPError = ASPERR_NoError;
return(sp);
}
static session_t *
createSess(fd, SPError)
int fd;
int *SPError;
{
session_t *sp = (session_t *)NULL;
if ((sp = findSess(fd, SPError)))
at_rwl_writelock(&(sp->RWLock));
else {
if (*SPError != ASPERR_ParamErr)
if ((sp = malloc(sizeof(session_t)))) {
*SPError = ASPERR_NoError;
Session[fd] = sp;
initSess(sp);
at_rwl_writelock(&(sp->RWLock));
} else
*SPError = ASPERR_NoMoreSessions;
}
return(sp);
}
void
deleteSess(fd)
int fd;
{
int err;
session_t *sp = findSess(fd, &err);
if (sp)
initSess(sp);
}
static session_t *
readSess(fd, SPError)
int fd;
int *SPError;
{
session_t *sp = findSess(fd, SPError);
if (sp)
at_rwl_readlock(&(sp->RWLock));
return(sp);
}
static session_t *
writeSess(fd, SPError)
int fd;
int *SPError;
{
session_t *sp = findSess(fd, SPError);
if (sp)
at_rwl_writelock(&(sp->RWLock));
return(sp);
}
static listener_t *
find_SLS(refNum)
int refNum;
{
int i;
for (i = 0; i < ASPDEF_MaxNumOfSLS; i++) {
if (Listener[i].SLSRefNum == refNum)
return(&Listener[i]);
}
return((listener_t *)NULL);
}
static listener_t *
find_lsock(socket)
int socket;
{
int i;
for (i = 0; i < ASPDEF_MaxNumOfSLS; i++) {
if (Listener[i].AT_addr.socket == socket)
return(&Listener[i]);
}
return((listener_t *)NULL);
}
static ASP_init_done = 0;
void
asp_init(void)
{
int i;
if (ASP_init_done++)
return;
for (i = 0; i < ASPDEF_DefMaxDescr; i++) {
Session[i] = (session_t *)NULL;
}
for (i = 0; i < ASPDEF_MaxNumOfSLS; i++) {
Listener[i].SLSRefNum = 0;
Listener[i].IN_descr = 0;
}
}
int
SPAttention(int SessRefNum,
unsigned short AttentionCode,
int *SPError,
int NoWait)
{
int CmdResult, rval, len;
session_t *sp;
char tmpBuf[ASPDEF_MaxCmdSize];
#ifdef ASPDEBUG
char *rn = "SPAttention";
#endif
LOG_MSG(rn, SessRefNum);
if (SendCommand(SessRefNum,
&AttentionCode, 2, SPError, ASPFUNC_Attention) == -1)
return -1;
if (NoWait) {
*SPError = ASPERR_NoError;
return 0;
}
if ((rval = SPGetReply(SessRefNum, tmpBuf, sizeof(tmpBuf),
&CmdResult, &len, SPError))) {
if (rval == -1)
return rval;
if ((sp = writeSess(SessRefNum, SPError))) {
sp->NewReqLen = len;
memcpy(sp->NewReqBuf, tmpBuf, sizeof(tmpBuf));
sp->NewReqType = rval;
sp->NewReqRefNum = CmdResult;
at_rwl_writeunlock(&(sp->RWLock));
}
if ((rval = SPGetReply(SessRefNum, 0, 0, &CmdResult, 0,
SPError)))
return rval;
}
*SPError = ASPERR_NoError;
return 0;
}
int
SPCloseSession(int SessRefNum,
int *SPError)
{
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPCloseSession";
#endif
if (!(sp = writeSess(SessRefNum, SPError))) {
LOG_ERR(rn);
return -1;
}
if (sp->SessType != ASPDT_TCP_FS) {
(void)at_send_to_dev(SessRefNum, ASPIOC_CloseSession, 0, 0);
}
close(SessRefNum);
at_rwl_writeunlock(&(sp->RWLock));
deleteSess(SessRefNum);
LOG_MSG(rn, SessRefNum);
*SPError = ASPERR_NoError;
return 0;
}
int
SPCmdReply(int SessRefNum,
unsigned short ReqRefNum,
int CmdResult,
char *CmdReplyData,
int CmdReplyDataSize,
int *SPError)
{
struct iovec iov[2];
union asp_primitives *primitives;
strbuf_t data;
strbuf_t ctrl;
char ctrlbuf[ASPDEF_BufSize];
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPCmdReply";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_TCP_FS) {
int quantumSize;
char fspktbuf[sizeof(asp_fspkt_t)+256];
asp_fspkt_t *fspkt = (asp_fspkt_t *)fspktbuf;
if (sp->UserType)
quantumSize = sp->Quantum;
else {
if (FSQuantumSize == 0)
FSQuantumSize = GetQuantumSize();
quantumSize = FSQuantumSize;
}
if (CmdReplyDataSize > quantumSize) {
SET_ERRNO(ERANGE);
*SPError = ASPERR_SizeErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
fspkt->Flags = ASPFS_Reply;
fspkt->Command = ASPFUNC_Command;
fspkt->RequestID = ReqRefNum;
fspkt->ErrorCode = CmdResult;
fspkt->TotalLen = CmdReplyDataSize;
fspkt->Reserved = 0;
iov[0].iov_base = (caddr_t)fspkt;
iov[0].iov_len = sizeof(*fspkt);
iov[1].iov_base = (caddr_t)CmdReplyData;
iov[1].iov_len = CmdReplyDataSize;
if (writev(SessRefNum, iov, 2) == -1) {
*SPError = (errno == EINVAL) ? ASPERR_ParamErr : ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
} else {
if (CmdReplyDataSize > ASPDEF_QuantumSize) {
SET_ERRNO(ERANGE);
*SPError = ASPERR_SizeErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
primitives = (union asp_primitives *)ctrlbuf;
primitives->CmdReplyReq.Primitive = ASPFUNC_CmdReply;
primitives->CmdReplyReq.CmdResult = CmdResult;
primitives->CmdReplyReq.ReqRefNum = ReqRefNum;
ctrl.len = sizeof(ctrlbuf);
ctrl.buf = ctrlbuf;
data.len = CmdReplyDataSize;
data.buf = CmdReplyData;
if (ATputmsg(SessRefNum, &ctrl, &data, 1) == -1) {
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else if (errno == EAGAIN)
*SPError = ASPERR_ProtoErr;
else
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
}
*SPError = ASPERR_NoError;
at_rwl_readunlock(&(sp->RWLock));
LOG_MSG(rn, SessRefNum);
return 0;
}
void
SPGetParms(int *MaxCmdSize,
int *QuantumSize,
int SessRefNum)
{
int err;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPGetParms";
#endif
LOG_MSG(rn, SessRefNum);
*MaxCmdSize = ASPDEF_MaxCmdSize;
*QuantumSize = ASPDEF_QuantumSize;
if (!(sp = readSess(SessRefNum, &err))) {
LOG_ERR(rn);
return;
}
if (sp->SessType == ASPDT_TCP_FS)
if (sp->UserType)
*QuantumSize = sp->Quantum;
else
*QuantumSize = GetQuantumSize();
at_rwl_readunlock(&(sp->RWLock));
}
int
SPGetRequest(int SessRefNum,
char *ReqBuff,
int ReqBuffSize,
unsigned short *ReqRefNum,
int *ReqType,
int *ActRcvdReqLen,
int *SPError)
{
int rval;
union asp_primitives *primitives;
strbuf_t data;
strbuf_t ctrl;
char ctrlbuf[ASPDEF_BufSize];
asp_fspkt_t *fspkt;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPGetRequest";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
SET_ERRNO(EBADF);
LOG_ERR(rn);
return -1;
}
if (sp->NewReqType) {
memcpy(ReqBuff, sp->NewReqBuf, sp->NewReqLen);
*ReqType = sp->NewReqType;
*ReqRefNum = sp->NewReqRefNum;
*ActRcvdReqLen = sp->NewReqLen;
sp->NewReqType = 0;
*SPError = ASPERR_NoError;
at_rwl_readunlock(&(sp->RWLock));
LOG_MSG(rn, SessRefNum);
return 0;
}
fspkt = (asp_fspkt_t *)&sp->SessFSPkt;
if (sp->SessType == ASPDT_TCP_FS) {
int len, len_left, sum = 0;
if ((!sp->FSRangeErr) || (sp->SessFSPkt.Flags & ASPFS_Reply)) {
while (1) {
if (recv(SessRefNum, (char *)fspkt, sizeof(*fspkt), 0) != sizeof(*fspkt)) {
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (fspkt->Command != ASPFUNC_Tickle)
break;
send(SessRefNum, (char *)fspkt, sizeof(*fspkt),MSG_EOR);
}
}
if (fspkt->Command == ASPFUNC_Write) {
if (fspkt->ErrorCode == 0)
fspkt->ErrorCode = fspkt->TotalLen;
len_left = fspkt->ErrorCode;
} else
len_left = fspkt->TotalLen;
sp->FSRangeErr = 0;
if (len_left > ReqBuffSize) {
sp->FSRangeErr = 1;
SET_ERRNO(ERANGE);
*SPError = ASPERR_BufTooSmall;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
while (len_left && ((len = recv(SessRefNum,
(char *)&ReqBuff[sum], len_left, 0)) > 0)) {
sum += len;
len_left -= len;
}
if (len_left) {
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
*ActRcvdReqLen = sum;
if (fspkt->Flags & ASPFS_Reply) {
*ReqRefNum = fspkt->ErrorCode;
SET_ERRNO(EPROTOTYPE);
*SPError = ASPERR_CmdReply;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return 1;
}
*ReqRefNum = fspkt->RequestID;
*ReqType = (int)fspkt->Command;
} else {
primitives = (union asp_primitives *)ctrlbuf;
ctrl.maxlen = sizeof(ctrlbuf);
ctrl.len = 0;
ctrl.buf = ctrlbuf;
data.maxlen = ReqBuffSize;
data.len = 0;
data.buf = ReqBuff;
while ((rval = ATgetmsg(SessRefNum, &ctrl, &data, 0)) == -1) {
if (errno == EINTR)
continue;
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (rval & MOREDATA) {
SET_ERRNO(ERANGE);
*SPError = ASPERR_BufTooSmall;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (ctrl.len == 0) {
SET_ERRNO(ENOTCONN);
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
return -1;
}
if (primitives->CommandInd.Primitive == ASPFUNC_CmdReply) {
if (ctrl.len == sizeof(asp_cmdreply_ind_t)) {
if ((*ActRcvdReqLen = data.len) < 0)
*ActRcvdReqLen = 0;
*ReqRefNum = primitives->CmdReplyInd.CmdResult;
SET_ERRNO(EPROTOTYPE);
*SPError = ASPERR_CmdReply;
at_rwl_readunlock(&(sp->RWLock));
return 1;
} else {
SET_ERRNO(EPROTOTYPE);
*SPError = ASPERR_ProtoErr;
}
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
*ReqRefNum = primitives->CommandInd.ReqRefNum;
*ReqType = (int)primitives->CommandInd.ReqType;
if ((*ActRcvdReqLen = data.len) < 0)
*ActRcvdReqLen = 0;
}
*SPError = ASPERR_NoError;
at_rwl_readunlock(&(sp->RWLock));
LOG_MSG(rn, SessRefNum);
return 0;
}
int
SPGetSession(int SLSRefNum,
int *SessRefNum,
int *SPError)
{
int ret;
char descr_type;
int ws, fs_conn_descr = -1;
int ic_len, descr = -1;
at_inet_t addr;
fd_set readfds;
int nfds;
struct timeval tv;
listener_t *lp;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPGetSession";
#endif
asp_init();
LOG_MSG(rn, SLSRefNum);
if (!(lp = find_SLS(SLSRefNum))) {
SET_ERRNO(ENOENT);
*SPError = ASPERR_NoSuchEntity;
LOG_ERR(rn);
return -1;
}
if (FSListenPort && lp->IN_descr)
fs_conn_descr = lp->IN_descr;
l_again:
if (fs_conn_descr != -1) {
FD_ZERO(&readfds);
FD_SET(SLSRefNum, &readfds);
FD_SET(fs_conn_descr, &readfds);
nfds = ((SLSRefNum > fs_conn_descr)? SLSRefNum : fs_conn_descr) + 1;
if ((ret = select(nfds, &readfds, 0, 0, 0)) <= 0) {
if ((errno == EINTR) || (ret == 0))
goto l_again;
else {
*SPError = ASPERR_SystemErr;
goto l_error;
}
} else {
if (FD_ISSET(SLSRefNum, &readfds))
descr_type = ASPDT_ATP_AS;
else if (FD_ISSET(fs_conn_descr, &readfds))
descr_type = ASPDT_TCP_FS;
else
goto l_again;
}
} else {
while (ATgetmsg(SLSRefNum, 0, 0, 0) == -1) {
if (errno == EINTR)
continue;
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else
*SPError = ASPERR_SessClosed;
LOG_ERR(rn);
return -1;
}
descr_type = ASPDT_ATP_AS;
}
if (descr_type == ASPDT_TCP_FS) {
char fspktbuf[32], optbuf[ASPFS_MaxOptLen];
asp_fspkt_t *fspkt = (asp_fspkt_t *)fspktbuf;
struct sockaddr_in in_addr;
int in_addrlen = sizeof(in_addr);
int len, len_left;
asp_opt_t *opt;
if ((descr = accept(fs_conn_descr, (void *)&in_addr, &in_addrlen)) == -1) {
*SPError = ASPERR_ProtoErr;
goto l_error;
}
tv.tv_sec = 10; tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(descr, &readfds);
nfds = descr + 1;
if ((select(nfds, &readfds, 0, 0, (void *)&tv) <= 0)
|| (recv(descr, (char *)fspkt, sizeof(*fspkt), 0) != sizeof(*fspkt))) {
close(descr);
goto l_again;
}
switch (fspkt->Command) {
case ASPFUNC_OpenSess:
len_left = fspkt->TotalLen;
if ((len_left < 0) || (len_left > ASPFS_MaxOptLen))
goto l_paramErr;
tv.tv_sec = ASP_CONN_TIMEOUT; tv.tv_usec = 0;
setsockopt(descr, SOL_SOCKET,SO_RCVTIMEO,(void *)&tv, sizeof(tv));
while (len_left
&& ((len = recv(descr, &optbuf[fspkt->TotalLen-len_left],
len_left,0)) > 0)) {
len_left -= len;
}
if (len_left)
goto l_paramErr;
tv.tv_sec = ASP_SESS_TIMEOUT; tv.tv_usec = 0;
ws = 0x10000;
setsockopt(descr, SOL_SOCKET,SO_SNDBUF,(void *)&ws, sizeof(ws));
setsockopt(descr, SOL_SOCKET,SO_RCVBUF,(void *)&ws, sizeof(ws));
setsockopt(descr, SOL_SOCKET,SO_RCVTIMEO,(void *)&tv, sizeof(tv));
fspkt->Flags = ASPFS_Reply;
fspkt->Command = ASPFUNC_OpenSess;
fspkt->ErrorCode = 0;
fspkt->TotalLen = 6;
fspkt->Reserved = 0;
opt = (asp_opt_t *)(fspkt+1);
opt->tag = ASPFS_DataQuantumTag;
opt->len = sizeof(int);
*(int *)opt->val = FSQuantumSize;
send(descr, (char *)fspkt, sizeof(*fspkt)+fspkt->TotalLen,MSG_EOR);
break;
case ASPFUNC_GetStatus:
if (fspkt->TotalLen == 0) {
*(asp_fspkt_t *)FSStatusBlk = *fspkt;
fspkt = (asp_fspkt_t *)FSStatusBlk;
fspkt->Flags = ASPFS_Reply;
fspkt->Command = ASPFUNC_GetStatus;
fspkt->ErrorCode = 0;
fspkt->TotalLen = FSStatusLen;
fspkt->Reserved = 0;
send(descr, FSStatusBlk, sizeof(*fspkt)+fspkt->TotalLen,MSG_EOR);
goto l_cmdDone;
}
default:
l_paramErr:
fspkt->Flags = ASPFS_Reply;
fspkt->ErrorCode = ASPERR_ParamErr;
fspkt->TotalLen = 0;
fspkt->Reserved = 0;
send(descr, (char *)fspkt, sizeof(*fspkt),MSG_EOR);
l_cmdDone:
tv.tv_sec = 2; tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(descr, &readfds);
nfds = descr + 1;
select(nfds, &readfds, 0, 0, (void *)&tv);
close(descr);
goto l_again;
}
} else {
addr.socket = lp->AT_addr.socket;
addr.net = (u_short)DefSessionTimer;
addr.node = (unsigned char)DefTickleInterval;
descr = ATsocket(ATPROTO_ASP);
if (descr == -1) {
*SPError = ASPERR_NoSuchDevice;
LOG_ERR(rn);
return -1;
}
ic_len = sizeof(addr);
while (at_send_to_dev(descr, ASPIOC_GetSession, (char *) &addr, &ic_len) == -1) {
if (errno != EAGAIN) {
*SPError = ASPERR_SystemErr;
goto l_error;
}
ic_len = sizeof(addr);
sleep(1);
}
}
if (!(sp = createSess(descr, SPError))) {
goto l_error;
}
sp->SessType = descr_type;
at_rwl_writeunlock(&(sp->RWLock));
*SessRefNum = descr;
*SPError = ASPERR_NoError;
LOG_MSG(rn, descr);
return 0;
l_error:
if (descr != -1)
close(descr);
LOG_ERR(rn);
return -1;
}
int
SPInit(at_inet_t *SLSEntityIdentifier,
char *ServiceStatusBlock,
int ServiceStatusBlockSize,
int *SLSRefNum,
int *SPError)
{
listener_t *lp;
#ifdef ASPDEBUG
char *rn = "SPInit";
#endif
if (!(lp = find_lsock(SLSEntityIdentifier->socket))) {
SET_ERRNO(ENOENT);
*SPError = ASPERR_NoSuchEntity;
LOG_ERR(rn);
return -1;
}
*SLSRefNum = lp->SLSRefNum;
LOG_MSG(rn, *SLSRefNum);
return SPNewStatus(*SLSRefNum, ServiceStatusBlock,
ServiceStatusBlockSize, SPError);
}
int
SPNewStatus(int SLSRefNum,
char *ServiceStatusBlock,
int ServiceStatusBlockSize,
int *SPError)
{
int ic_len;
listener_t *lp;
#ifdef ASPDEBUG
char *rn = "SPNewStatus";
#endif
if (ServiceStatusBlockSize > ASPDEF_QuantumSize) {
SET_ERRNO(ERANGE);
*SPError = ASPERR_SizeErr;
LOG_ERR(rn);
return -1;
}
if (FSListenPort) {
if (!(lp = find_SLS(SLSRefNum))) {
SET_ERRNO(ENOENT);
*SPError = ASPERR_NoSuchEntity;
LOG_ERR(rn);
return -1;
}
if (lp->IN_descr) {
int len, sblk_len, tcp_len, pad;
unsigned char *sblk_ptr;
asp_svrinfo_t *svrinfo;
asp_tcpinfo_t *tcpinfo;
unsigned short VolumeIconOffset;
if ((VolumeIconOffset = ((asp_svrinfo_t *)
ServiceStatusBlock)->VolumeIconOffset) == 0)
VolumeIconOffset = ServiceStatusBlockSize;
len = sizeof(asp_svrinfo_t) + 1 + (int)((unsigned char)ServiceStatusBlock[sizeof(asp_svrinfo_t)]);
sblk_ptr = &FSStatusBlk[sizeof(asp_fspkt_t)];
memcpy(sblk_ptr, ServiceStatusBlock, len);
pad = (len & 1) ? 1 : 0;
sblk_len = len + pad;
tcpinfo = (asp_tcpinfo_t *)&sblk_ptr[sblk_len];
sblk_len += sizeof(asp_tcpinfo_t);
tcpinfo->SigDataOffset = VolumeIconOffset + pad+sizeof(asp_tcpinfo_t);
tcpinfo->TCPDataOffset = tcpinfo->SigDataOffset + ASPFS_SigDataLen;
GetSigInfo(&sblk_ptr[tcpinfo->SigDataOffset]);
sblk_ptr[tcpinfo->TCPDataOffset] =
GetTCPInfo(&sblk_ptr[tcpinfo->TCPDataOffset+1], lp->IN_port);
tcp_len = (ASPFS_SigDataLen + 1 +
(sizeof(asp_tcpaddr_t)*sblk_ptr[tcpinfo->TCPDataOffset]));
svrinfo = (asp_svrinfo_t *)&FSStatusBlk[sizeof(asp_fspkt_t)];
if (svrinfo->MachineTypeOffset)
svrinfo->MachineTypeOffset += (pad+sizeof(asp_tcpinfo_t));
if (svrinfo->AFPVersionsOffset)
svrinfo->AFPVersionsOffset += (pad+sizeof(asp_tcpinfo_t));
if (svrinfo->UAMsOffset)
svrinfo->UAMsOffset += (pad+sizeof(asp_tcpinfo_t));
if (svrinfo->VolumeIconOffset) {
svrinfo->VolumeIconOffset += (pad+sizeof(asp_tcpinfo_t)+tcp_len);
memcpy((char *)&sblk_ptr[svrinfo->VolumeIconOffset],
&ServiceStatusBlock[VolumeIconOffset],
ServiceStatusBlockSize-VolumeIconOffset);
}
svrinfo->Flags |= (ASPFS_SigSuppBit | ASPFS_TCPSuppBit);
memcpy((char *)&sblk_ptr[sblk_len],
&ServiceStatusBlock[len], VolumeIconOffset-len);
ServiceStatusBlockSize += (pad+sizeof(asp_tcpinfo_t)+tcp_len);
FSStatusLen = ServiceStatusBlockSize;
ServiceStatusBlock = &FSStatusBlk[sizeof(asp_fspkt_t)];
}
}
ic_len = ServiceStatusBlockSize;
if (at_send_to_dev(SLSRefNum, ASPIOC_StatusBlock,
ServiceStatusBlock, &ic_len) == -1) {
*SPError = ASPERR_ParamErr;
LOG_ERR(rn);
return -1;
}
*SPError = ASPERR_NoError;
LOG_MSG(rn, SLSRefNum);
return 0;
}
int
SPWrtContinue(int SessRefNum,
unsigned short ReqRefNum,
char *Buff,
int BuffSize,
int *ActLenRcvd,
int *SPError,
int NoWait)
{
char CmdBlock[2];
int CmdBlockSize;
int CmdResult;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPWrtContinue";
#endif
LOG_MSG(rn, SessRefNum);
if (!(sp = readSess(SessRefNum, SPError))) {
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_TCP_FS) {
asp_fspkt_t *fspkt = &sp->SessFSPkt;
int len, len_left, sum = 0, d_len = 0;
char d_buf[1024];
len_left = fspkt->TotalLen - fspkt->ErrorCode;
if (len_left > BuffSize) {
d_len = len_left - BuffSize;
len_left = BuffSize;
}
while (len_left && ((len = recv(SessRefNum,
(char *)&Buff[sum], len_left, 0)) > 0)) {
sum += len;
len_left -= len;
}
if (len_left) {
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (d_len) {
len = (d_len < sizeof(d_buf)) ? d_len : sizeof(d_buf);
while (d_len && ((len = recv(SessRefNum, d_buf, len, 0)) > 0)) {
d_len -= len;
len = (d_len < sizeof(d_buf)) ? d_len : sizeof(d_buf);
}
}
*ActLenRcvd = sum;
*SPError = ASPERR_NoError;
at_rwl_readunlock(&(sp->RWLock));
return 0;
} else {
CmdBlockSize = 2;
*(unsigned short *)&CmdBlock[0] = BuffSize;
if (SendCommand(SessRefNum,
CmdBlock, CmdBlockSize, SPError, ASPFUNC_WriteContinue) == -1) {
at_rwl_readunlock(&(sp->RWLock));
return -1;
}
if (NoWait) {
*SPError = ASPERR_NoError;
at_rwl_readunlock(&(sp->RWLock));
return 0;
}
at_rwl_readunlock(&(sp->RWLock));
return SPGetReply(SessRefNum, Buff,
BuffSize, &CmdResult, ActLenRcvd, SPError);
}
}
int
SPWrtReply(int SessRefNum,
unsigned short ReqRefNum,
int CmdResult,
char *CmdReplyData,
int CmdReplyDataSize,
int *SPError)
{
#ifdef ASPDEBUG
char *rn = "SPWrtReply";
#endif
LOG_MSG(rn, SessRefNum);
return SPCmdReply(SessRefNum, ReqRefNum,
CmdResult, CmdReplyData, CmdReplyDataSize, SPError);
}
int
SPGetReply(int SessRefNum,
char *ReplyBuffer,
int ReplyBufferSize,
int *CmdResult,
int *ActRcvdReplyLen,
int *SPError)
{
int rval;
union asp_primitives *primitives;
strbuf_t data;
strbuf_t ctrl;
char ctrlbuf[ASPDEF_BufSize];
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPGetReply";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
SET_ERRNO(EBADF);
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_TCP_FS) {
asp_fspkt_t fspktbuf, *fspkt = &fspktbuf;
int len, len_left, sum = 0;
if (sp->FSRangeErr && (sp->SessFSPkt.Flags & ASPFS_Reply)) {
*fspkt = sp->SessFSPkt;
sp->SessFSPkt.Flags = 0;
} else {
if (recv(SessRefNum, (char *)fspkt, sizeof(*fspkt), 0) != sizeof(*fspkt)) {
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
}
if (fspkt->Flags & ASPFS_Reply)
len_left = fspkt->TotalLen;
else {
len_left = fspkt->TotalLen;
if (fspkt->Command == ASPFUNC_Write) {
sp->SessFSPkt = *fspkt;
if (fspkt->ErrorCode)
len_left = fspkt->ErrorCode;
}
}
sp->FSRangeErr = 0;
if (len_left > ReplyBufferSize) {
if (fspkt->Flags & ASPFS_Reply) {
sp->FSRangeErr = 1;
sp->SessFSPkt = *fspkt;
}
SET_ERRNO(ERANGE);
*SPError = ASPERR_BufTooSmall;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
while (len_left && ((len = recv(SessRefNum,
(char *)&ReplyBuffer[sum], len_left, 0)) > 0)) {
sum += len;
len_left -= len;
}
if (len_left) {
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (!(fspkt->Flags & ASPFS_Reply)) {
SET_ERRNO(EPROTOTYPE);
*SPError = ASPERR_CmdRequest;
*CmdResult = (int)fspkt->RequestID;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return (int)fspkt->Command;
}
*CmdResult = (int)fspkt->ErrorCode;
if (ReplyBufferSize)
*ActRcvdReplyLen = sum;
} else {
primitives = (union asp_primitives *)ctrlbuf;
ctrl.maxlen = sizeof(ctrlbuf);
ctrl.len = 0;
ctrl.buf = ctrlbuf;
data.maxlen = ReplyBufferSize;
data.len = 0;
data.buf = ReplyBuffer;
while ((rval = ATgetmsg(SessRefNum, &ctrl, &data, 0)) == -1) {
if (errno == EINTR)
continue;
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (rval & MOREDATA) {
SET_ERRNO(ERANGE);
*SPError = ASPERR_BufTooSmall;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (ctrl.len == 0) {
SET_ERRNO(ENOTCONN);
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (primitives->CmdReplyInd.Primitive != ASPFUNC_CmdReply) {
if (ctrl.len == sizeof(asp_command_ind_t)) {
if ((*ActRcvdReplyLen = data.len) < 0)
*ActRcvdReplyLen = 0;
SET_ERRNO(EPROTOTYPE);
*SPError = ASPERR_CmdRequest;
*CmdResult = (int)primitives->CommandInd.ReqRefNum;
at_rwl_readunlock(&(sp->RWLock));
return (int)primitives->CommandInd.ReqType;
} else {
SET_ERRNO(EPROTOTYPE);
*SPError = ASPERR_ProtoErr;
}
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
*CmdResult = primitives->CmdReplyInd.CmdResult;
if (ReplyBufferSize) {
if ((*ActRcvdReplyLen = data.len) < 0)
*ActRcvdReplyLen = 0;
}
}
at_rwl_readunlock(&(sp->RWLock));
*SPError = ASPERR_NoError;
LOG_MSG(rn, SessRefNum);
return 0;
}
int
SPLook(int SessRefNum,
int *SPError)
{
int rval, nfds;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPLook";
#endif
LOG_MSG(rn, SessRefNum);
if (!(sp = readSess(SessRefNum, SPError))) {
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_TCP_FS) {
asp_fspkt_t fspktbuf, *fspkt = &fspktbuf;
struct timeval tv;
fd_set readfds;
SET_ERRNO(0);
*SPError = ASPERR_NoError;
tv.tv_sec = 0; tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(SessRefNum, &readfds);
nfds = SessRefNum + 1;
if ((select(nfds, &readfds, 0, 0, (void *)&tv) <= 0)
|| (recv(SessRefNum, (char *)fspkt, sizeof(*fspkt), MSG_PEEK)
!= sizeof(*fspkt))) {
if (errno) {
if (errno != ENXIO)
*SPError = ASPERR_SystemErr;
else
*SPError = ASPERR_SessClosed;
}
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
if (fspkt->Command == ASPFUNC_Tickle) {
if ((recv(SessRefNum, (char *)fspkt, sizeof(*fspkt), 0)
!= sizeof(*fspkt))
|| (send(SessRefNum, (char *)fspkt, sizeof(*fspkt), MSG_EOR)
!= sizeof(*fspkt))) {
if (errno == ENXIO)
*SPError = ASPERR_SessClosed;
else if (errno)
*SPError = ASPERR_SystemErr;
LOG_ERR(rn);
}
at_rwl_readunlock(&(sp->RWLock));
return -1;
}
rval = (fspkt->Flags & ASPFS_Reply) ? 0 : 1;
at_rwl_readunlock(&(sp->RWLock));
return rval;
} else {
int ic_len;
*SPError = ASPERR_NoError;
ic_len = sizeof(rval);
if (at_send_to_dev(SessRefNum, ASPIOC_Look, (char *) &rval, &ic_len) == -1) {
if (errno != ENXIO)
*SPError = ASPERR_SystemErr;
else
*SPError = ASPERR_SessClosed;
LOG_ERR(rn);
at_rwl_readunlock(&(sp->RWLock));
return -1;
}
at_rwl_readunlock(&(sp->RWLock));
return rval;
}
}
int
SPRegister(at_entity_t *SLSEntity,
at_retry_t *Retry,
at_inet_t *SLSEntityIdentifier,
int *SPError)
{
unsigned short fs_port = 0xdead;
int on, ws, fs_conn_descr = -1;
int ic_len;
listener_t *lp;
int descr = -1;
struct sockaddr_in in_addr;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPRegister";
#endif
#ifdef ASPDEBUG
logfp = fopen("/tmp/asp.log", "a");
#endif
asp_init();
FSQuantumSize = ASPDEF_QuantumSize;
#if 0
FSQuantumSize = GetQuantumSize();
FSListenPort = GetListenPort(0, (void *)0, 0);
if (FSListenPort
&& !strncmp(SLSEntity->type.str, "AFPServer", SLSEntity->type.len)) {
if ((fs_conn_descr = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
*SPError = ASPERR_NoSuchDevice;
goto l_error;
}
on = 1;
ws = 0x10000;
setsockopt(fs_conn_descr, SOL_SOCKET,SO_SNDBUF,(void *)&ws,sizeof(ws));
setsockopt(fs_conn_descr, SOL_SOCKET,SO_RCVBUF,(char *)&ws,sizeof(ws));
setsockopt(fs_conn_descr, SOL_SOCKET,SO_REUSEADDR,(void *)&on,sizeof(on));
memset((char *)&in_addr, 0, sizeof(in_addr));
fs_port = FSListenPort;
in_addr.sin_family = PF_INET;
in_addr.sin_port = fs_port;
if (bind(fs_conn_descr, (void *)&in_addr, sizeof(in_addr)) == -1) {
if (errno == EADDRINUSE) {
int in_addrlen = sizeof(in_addr);
in_addr.sin_port = 0;
if (bind(fs_conn_descr, (void *)&in_addr, sizeof(in_addr)) == -1) {
*SPError = ASPERR_BindErr;
goto l_error;
}
if (getsockname(fs_conn_descr, (void *)&in_addr, &in_addrlen) == -1) {
*SPError = ASPERR_SystemErr;
goto l_error;
}
fs_port = in_addr.sin_port;
} else {
*SPError = ASPERR_BindErr;
goto l_error;
}
}
if (listen(fs_conn_descr, 1) == -1) {
*SPError = ASPERR_NoMoreSessions;
goto l_error;
}
LOG_MSG(rn, fs_conn_descr);
}
#endif
if (!(lp = find_lsock(0))) {
*SPError = ASPERR_NoMoreSessions;
goto l_error;
}
descr = ATsocket(ATPROTO_ASP);
if (descr == -1) {
*SPError = ASPERR_NoSuchDevice;
goto l_error;
}
ic_len = sizeof(at_inet_t);
if (at_send_to_dev(descr, ASPIOC_ListenerBind,
(char *) SLSEntityIdentifier, &ic_len) == -1) {
*SPError = ASPERR_NoMoreSessions;
goto l_error;
}
if (nbp_register(SLSEntity, descr, Retry) == -1) {
*SPError = ASPERR_RegisterErr;
goto l_error;
}
if (!(sp = createSess(descr, SPError))) {
goto l_error;
}
sp->SessType = ASPDT_ATP_AS;
at_rwl_writeunlock(&(sp->RWLock));
lp->AT_addr = *SLSEntityIdentifier;
lp->SLSRefNum = descr;
if (fs_conn_descr != -1) {
assert(fs_port != 0xdead);
lp->IN_port = fs_port;
lp->IN_descr = fs_conn_descr;
if (!(sp = createSess(fs_conn_descr, SPError))) {
goto l_error;
}
sp->SessType = ASPDT_TCP_FS;
at_rwl_writeunlock(&(sp->RWLock));
}
*SPError = ASPERR_NoError;
LOG_MSG(rn, descr);
return 0;
l_error:
if (fs_conn_descr != -1)
close(fs_conn_descr);
if (descr != -1)
close(descr);
LOG_ERR(rn);
return -1;
}
int
SPRegisterWithTCPPossibility(at_entity_t *SLSEntity,
at_retry_t *Retry,
at_inet_t *SLSEntityIdentifier,
int *SPError)
{
unsigned short fs_port = 0xdead;
int on, ws, fs_conn_descr = -1;
int ic_len;
listener_t *lp;
int descr = -1;
struct sockaddr_in in_addr;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPRegister";
#endif
#ifdef ASPDEBUG
logfp = fopen("/tmp/asp.log", "a");
#endif
asp_init();
FSQuantumSize = GetQuantumSize();
FSListenPort = GetListenPort(0, (void *)0, 0);
if (FSListenPort
&& !strncmp(SLSEntity->type.str, "AFPServer", SLSEntity->type.len)) {
if ((fs_conn_descr = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
*SPError = ASPERR_NoSuchDevice;
goto l_error;
}
on = 1;
ws = 0x10000;
setsockopt(fs_conn_descr, SOL_SOCKET,SO_SNDBUF,(void *)&ws,sizeof(ws));
setsockopt(fs_conn_descr, SOL_SOCKET,SO_RCVBUF,(char *)&ws,sizeof(ws));
setsockopt(fs_conn_descr, SOL_SOCKET,SO_REUSEADDR,(void *)&on,sizeof(on));
memset((char *)&in_addr, 0, sizeof(in_addr));
fs_port = FSListenPort;
in_addr.sin_family = PF_INET;
in_addr.sin_port = fs_port;
if (bind(fs_conn_descr, (void *)&in_addr, sizeof(in_addr)) == -1) {
if (errno == EADDRINUSE) {
int in_addrlen = sizeof(in_addr);
in_addr.sin_port = 0;
if (bind(fs_conn_descr, (void *)&in_addr, sizeof(in_addr)) == -1) {
*SPError = ASPERR_BindErr;
goto l_error;
}
if (getsockname(fs_conn_descr, (void *)&in_addr, &in_addrlen) == -1) {
*SPError = ASPERR_SystemErr;
goto l_error;
}
fs_port = in_addr.sin_port;
} else {
*SPError = ASPERR_BindErr;
goto l_error;
}
}
if (listen(fs_conn_descr, 1) == -1) {
*SPError = ASPERR_NoMoreSessions;
goto l_error;
}
LOG_MSG(rn, fs_conn_descr);
}
if (!(lp = find_lsock(0))) {
*SPError = ASPERR_NoMoreSessions;
goto l_error;
}
descr = ATsocket(ATPROTO_ASP);
if (descr == -1) {
*SPError = ASPERR_NoSuchDevice;
goto l_error;
}
ic_len = sizeof(at_inet_t);
if (at_send_to_dev(descr, ASPIOC_ListenerBind,
(char *) SLSEntityIdentifier, &ic_len) == -1) {
*SPError = ASPERR_NoMoreSessions;
goto l_error;
}
if (nbp_register(SLSEntity, descr, Retry) == -1) {
*SPError = ASPERR_RegisterErr;
goto l_error;
}
if (!(sp = createSess(descr, SPError))) {
goto l_error;
}
sp->SessType = ASPDT_ATP_AS;
at_rwl_writeunlock(&(sp->RWLock));
lp->AT_addr = *SLSEntityIdentifier;
lp->SLSRefNum = descr;
if (fs_conn_descr != -1) {
assert(fs_port != 0xdead);
lp->IN_port = fs_port;
lp->IN_descr = fs_conn_descr;
if (!(sp = createSess(fs_conn_descr, SPError))) {
goto l_error;
}
sp->SessType = ASPDT_TCP_FS;
at_rwl_writeunlock(&(sp->RWLock));
}
*SPError = ASPERR_NoError;
LOG_MSG(rn, descr);
return 0;
l_error:
if (fs_conn_descr != -1)
close(fs_conn_descr);
if (descr != -1)
close(descr);
LOG_ERR(rn);
return -1;
}
int
SPRemove(at_entity_t *SLSEntity,
at_inet_t *SLSEntityIdentifier,
int *SPError)
{
listener_t *lp;
#ifdef ASPDEBUG
char *rn = "SPRemove";
#endif
if ( (!(lp = find_lsock(SLSEntityIdentifier->socket))) ||
(nbp_remove(SLSEntity, lp->SLSRefNum) == -1)) {
SET_ERRNO(ENOENT);
*SPError = ASPERR_NoSuchEntity;
LOG_ERR(rn);
return -1;
}
LOG_MSG(rn, lp->SLSRefNum);
close(lp->SLSRefNum);
lp->AT_addr.socket = 0;
lp->SLSRefNum = 0;
if (FSListenPort && lp->IN_descr) {
LOG_MSG(rn, lp->IN_descr);
close(lp->IN_descr);
lp->IN_descr = 0;
}
*SPError = ASPERR_NoError;
return 0;
}
void
SPConfigure(unsigned short TickleInterval,
unsigned short SessionTimer,
at_retry_t *Retry)
{
#ifdef ASPDEBUG
char *rn = "SPConfigure";
#endif
LOG_MSG(rn, 0);
if (TickleInterval)
DefTickleInterval = TickleInterval;
if (SessionTimer)
DefSessionTimer = SessionTimer;
if (Retry)
CmdRetry = *Retry;
}
int
SPGetLocEntity(int SessRefNum,
void *SessLocEntityIdentifier,
int *SPError)
{
int ic_len;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPGetLocEntity";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_TCP_FS) {
struct sockaddr_in in_addr;
int in_addrlen = sizeof(in_addr);
if (getsockname(SessRefNum, (void *)&in_addr, &in_addrlen) == -1) {
*SPError = ASPERR_SystemErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
*(unsigned long *)SessLocEntityIdentifier = in_addr.sin_addr.s_addr;
} else {
ic_len = sizeof(at_inet_t);
if (at_send_to_dev(SessRefNum, ASPIOC_GetLocEntity,
SessLocEntityIdentifier, &ic_len) == -1) {
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else
*SPError = ASPERR_SystemErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
}
at_rwl_readunlock(&(sp->RWLock));
*SPError = ASPERR_NoError;
LOG_MSG(rn, SessRefNum);
return 0;
}
int
SPGetRemEntity(int SessRefNum,
void *SessRemEntityIdentifier,
int *SPError)
{
int ic_len;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPGetRemEntity";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_TCP_FS) {
struct sockaddr_in in_addr;
int in_addrlen = sizeof(in_addr);
if (getpeername(SessRefNum, (void *)&in_addr, &in_addrlen) == -1) {
*SPError = ASPERR_SystemErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
*(unsigned long *)SessRemEntityIdentifier = in_addr.sin_addr.s_addr;
} else {
ic_len = sizeof(at_inet_t);
if (at_send_to_dev(SessRefNum, ASPIOC_GetRemEntity,
SessRemEntityIdentifier, &ic_len) == -1) {
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else
*SPError = ASPERR_SystemErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
}
at_rwl_readunlock(&(sp->RWLock));
*SPError = ASPERR_NoError;
LOG_MSG(rn, SessRefNum);
return 0;
}
void
SPErrorStr(char *msg,
int SPError)
{
char *pMsg;
if (SPError == 0) {
fprintf(stderr,MSGSTR(M_NO_ASP_ERR, "%s: no ASP error.\n"), msg);
return;
} else if ((SPError > -1058) || (SPError < -1075)) {
fprintf(stderr,MSGSTR(M_BAD_ASP_ERR,"%s: invalid ASP error\n"), msg);
return;
}
SPError = -(SPError + 1058);
switch (SPError) {
case 0:
pMsg = MSGSTR(M_NO_SUCH_DEV,"No such device");
break;
case 1:
pMsg = MSGSTR(M_ASP_BIND,"Can't bind to an ASP address");
break;
case 2:
pMsg = MSGSTR(M_CMD_REPLY,"Command reply message");
break;
case 3:
pMsg = MSGSTR(M_CMD_REQ,"Command request message");
break;
case 4:
pMsg = MSGSTR(M_SYSTEM_ERR,"System error");
break;
case 5:
pMsg = MSGSTR(M_PROTO_ERR,"Protocol error");
break;
case 6:
pMsg = MSGSTR(M_NO_SUCH_ENTITY,"No such entity");
break;
case 7:
pMsg = MSGSTR(M_CANT_REG,"Can't register the entity");
break;
case 8:
pMsg = MSGSTR(M_BAD_VER,"Version number not supported");
break;
case 9:
pMsg = MSGSTR(M_BUFFER,"Reply buffer cannot hold the whole reply");
break;
case 10:
pMsg = MSGSTR(M_SESSION,"Can't support another session");
break;
case 11:
pMsg = MSGSTR(M_NO_RESP,"Server is not responding");
break;
case 12:
pMsg = MSGSTR(M_REF_NO,"Reference number is unknown");
break;
case 13:
pMsg = MSGSTR(M_BUSY,"Server is busy");
break;
case 14:
pMsg = MSGSTR(M_CLOSED,"Session has been closed");
break;
case 15:
pMsg = MSGSTR(M_TOO_LARGE,"Command block size is too larger");
break;
case 16:
pMsg = MSGSTR(M_FULL,"Can't not support another client");
break;
case 17:
pMsg = MSGSTR(M_NAK,"No acknowledge");
break;
default:
pMsg=NULL;
}
if (pMsg)
printf("%s: %s\n", msg, pMsg);
}
int
SPSetPid(int SessRefNum,
int SessPid,
int *SPError)
{
int ic_len;
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPSetPid";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_ATP_AS) {
ic_len = sizeof(SessPid);
if (at_send_to_dev(SessRefNum, ASPIOC_SetPid, (char *) &SessPid, &ic_len) == -1) {
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else
*SPError = ASPERR_SystemErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
}
at_rwl_readunlock(&(sp->RWLock));
*SPError = ASPERR_NoError;
LOG_MSG(rn, SessRefNum);
return 0;
}
int
SPGetProtoFamily(int SessRefNum,
int *ProtoFamily,
int *SPError)
{
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SPGetProtoFamily";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
SET_ERRNO(EBADF);
LOG_ERR(rn);
return -1;
}
*ProtoFamily = (sp->SessType == ASPDT_TCP_FS) ?
PF_INET : PF_APPLETALK;
at_rwl_readunlock(&(sp->RWLock));
*SPError = ASPERR_NoError;
LOG_MSG(rn, SessRefNum);
return 0;
}
static int
SendCommand(int SessRefNum,
char *CmdBlock,
int CmdBlockSize,
int *SPError,
int Primitive)
{
strbuf_t data;
strbuf_t ctrl;
char ctrlbuf[ASPDEF_BufSize];
session_t *sp;
#ifdef ASPDEBUG
char *rn = "SendCommand";
#endif
if (!(sp = readSess(SessRefNum, SPError))) {
SET_ERRNO(EBADF);
LOG_ERR(rn);
return -1;
}
if (sp->SessType == ASPDT_TCP_FS) {
int fspktlen = sizeof(asp_fspkt_t);
char fspktbuf[sizeof(asp_fspkt_t)+256];
asp_fspkt_t *fspkt = (asp_fspkt_t *)fspktbuf;
if (CmdBlockSize > ASPDEF_MaxCmdSize) {
SET_ERRNO(ERANGE);
*SPError = ASPERR_SizeErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
fspkt->Flags = 0;
fspkt->Command = (unsigned char)Primitive;
fspkt->RequestID = FSRequestID++;
fspkt->ErrorCode = 0;
fspkt->TotalLen = CmdBlockSize;
fspkt->Reserved = 0;
if (CmdBlockSize <= (sizeof(fspktbuf)-sizeof(*fspkt))) {
memcpy((char *)(fspkt+1), CmdBlock, CmdBlockSize);
fspktlen += CmdBlockSize;
CmdBlockSize = 0;
}
if ( (send(SessRefNum, (char *)fspkt, fspktlen,
CmdBlockSize ? 0 : MSG_EOR) != fspktlen) ||
(CmdBlockSize &&
(send(SessRefNum, CmdBlock,
CmdBlockSize,MSG_EOR) != CmdBlockSize)) ) {
*SPError = (errno == EINVAL) ?
ASPERR_ParamErr : ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
} else {
if (CmdBlockSize > ASPDEF_MaxCmdSize) {
SET_ERRNO(ERANGE);
*SPError = ASPERR_SizeErr;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
((union asp_primitives *)ctrlbuf)->Primitive = Primitive;
ctrl.len = sizeof(ctrlbuf);
ctrl.buf = ctrlbuf;
data.len = CmdBlockSize;
data.buf = CmdBlock;
if (ATputmsg(SessRefNum, &ctrl, &data, 1) == -1) {
if (errno == EINVAL)
*SPError = ASPERR_ParamErr;
else if (errno == EAGAIN)
*SPError = ASPERR_ProtoErr;
else
*SPError = ASPERR_SessClosed;
at_rwl_readunlock(&(sp->RWLock));
LOG_ERR(rn);
return -1;
}
}
*SPError = ASPERR_NoError;
at_rwl_readunlock(&(sp->RWLock));
LOG_MSG(rn, SessRefNum);
return 0;
}
static int
GetQuantumSize()
{
int quantum = ASPDEF_QuantumSize;
FILE *fp;
if ((fp = fopen(ASPFS_AFPCfgName, "r")) != 0) {
char *p, *q;
char cfgbuf[ASP_LINE_LEN];
while (!feof(fp)) {
if (fgets(cfgbuf, sizeof(cfgbuf), fp) == 0)
break;
if (cfgbuf[0] == '#')
continue;
if ((p = strtok(cfgbuf, "\t \n")) == NULL)
continue;
q = strtok(NULL, "\t \n");
if (strpfx(p, "quantum") == 0) {
quantum = (int)atoi(q);
break;
}
}
}
return quantum;
}
static unsigned short
GetListenPort(int flag,
void *addr,
char *name)
{
unsigned short port = 0;
FILE *fp;
if ((fp = fopen(ASPFS_AFPCfgName, "r")) != 0) {
char *p, *q;
char cfgbuf[ASP_LINE_LEN];
port = DEFAULT_AFP_PORT;
while (!feof(fp)) {
if (fgets(cfgbuf, sizeof(cfgbuf), fp) == 0)
break;
if (cfgbuf[0] == '#')
continue;
if ((p = strtok(cfgbuf, "\t \n")) == NULL)
continue;
q = strtok(NULL, "\t \n");
if (strpfx(p, "disable") == 0) {
port = 0;
break;
}
if (strpfx(p, "port") == 0)
port = (unsigned short)atoi(q);
}
}
return port;
}
static unsigned char
GetTCPInfo(tcpaddr, port)
asp_tcpaddr_t *tcpaddr;
unsigned short port;
{
unsigned char cnt = 0;
unsigned long val;
FILE *fp;
if ((fp = fopen(ASPFS_AFPCfgName, "r")) != 0) {
char *p, *q;
char cfgbuf[ASP_LINE_LEN];
while (!feof(fp)) {
if (fgets(cfgbuf, sizeof(cfgbuf), fp) == 0)
break;
if (cfgbuf[0] == '#')
continue;
if ((p = strtok(cfgbuf, "\t \n")) == NULL)
continue;
q = strtok(NULL, "\t \n");
if (strpfx(p, "local") == 0) {
val = (unsigned long)inet_addr(q);
tcpaddr->len = 8;
tcpaddr->addr_tag = 2;
*(unsigned long *)tcpaddr->addr_value = val;
tcpaddr->port = port;
tcpaddr++;
cnt++;
}
}
}
if (cnt == 0) {
struct hostent *hostent;
char nambuf[ASP_LINE_LEN];
if (gethostname(nambuf, sizeof(nambuf)))
return 0;
hostent = (struct hostent *)gethostbyname(nambuf);
for (; (cnt < 255) && hostent->h_addr_list[cnt]; tcpaddr++, cnt++) {
val = *(unsigned long *)hostent->h_addr_list[cnt];
tcpaddr->len = 8;
tcpaddr->addr_tag = 2;
*(unsigned long *)tcpaddr->addr_value = val;
tcpaddr->port = port;
}
}
return cnt;
}
static void
GetSigInfo(buf)
char *buf;
{
static char nambuf[ASP_LINE_LEN];
memset((char *)buf, 0, ASPFS_SigDataLen);
gethostname(nambuf, sizeof(nambuf));
memcpy(buf, ASP_SIG_STR, 3);
sprintf(&buf[3], "%lx", gethostid());
memcpy(&buf[11], nambuf, ASPFS_SigDataLen-11);
}
static int
strpfx(pat, str)
char *pat;
char *str;
{
if ((pat == NULL) || (str == NULL) || (*pat == '\0') || (*str == '\0'))
return 0;
while (*pat && *str && (*pat == *str)) {
pat++;
str++;
}
return (int)*pat;
}