|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 26623 (0x67ff)
Types: TextFile
Names: »ts2bsd.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦e83f91978⟧ »EurOpenD22/isode/osimis-2.0.tar.Z«
└─⟦d846658bd⟧
└─⟦this⟧ »osimis/misode/tsap/ts2bsd.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z«
└─⟦de7628f85⟧
└─⟦this⟧ »isode-6.0/tsap/ts2bsd.c«
/* ts2bsd.c - TPM: 4.4BSD OSI TP4 interface */
#define STATIC /**/
#ifndef lint
static char *rcsid = "$Header: /f/osi/tsap/RCS/ts2bsd.c,v 7.6 89/12/19 10:18:28 mrose Exp $";
#endif
/*
* $Header: /f/osi/tsap/RCS/ts2bsd.c,v 7.6 89/12/19 10:18:28 mrose Exp $
*
*
* $Log: ts2bsd.c,v $
* Revision 7.6 89/12/19 10:18:28 mrose
* DLOG
*
* Revision 7.5 89/12/18 17:49:48 mrose
* touch-up
*
* Revision 7.4 89/12/08 16:26:47 mrose
* keith
*
* Revision 7.1 89/12/01 10:46:26 mrose
* touch-up
*
* Revision 7.0 89/11/23 22:30:36 mrose
* Release 6.0
*
*/
/*
* NOTICE
*
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
* this agreement.
*
*/
/* LINTLIBRARY */
#include <stdio.h>
#include "tpkt.h"
#ifdef TP4
#include "tp4.h"
#endif
#ifdef BSD_TP4
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include "tailor.h"
/*#define MAXTP4 8192 /* until we have a dynamic estimate... */
#define MAXTP4 1024 /* until we have a dynamic estimate... */
#define TP4SLOP 12 /* estimate of largest DT PCI */
/* \f
DATA */
STATIC struct msghdr msgs;
STATIC union osi_control_msg ocm;
extern int errno;
/* Ancillary routines */
STATIC int sendCmsg(fd, cc, type, data)
int fd;
int cc;
int type;
char *data;
{
int result;
register struct msghdr *msg = &msgs;
register union osi_control_msg *oc = &ocm;
bzero ((char *) msg, sizeof *msg);
msg -> msg_control = oc -> ocm_data;
bzero ((char *) oc, sizeof *oc);
oc -> ocm_control.ocm_cmhdr.cmsg_level = SOL_TRANSPORT;
oc -> ocm_control.ocm_cmhdr.cmsg_type = type;
oc -> ocm_control.ocm_cmhdr.cmsg_len = sizeof oc -> ocm_control.ocm_cmhdr;
if (cc) {
bcopy (data, oc -> ocm_control.ocm_cmdata, cc);
oc -> ocm_control.ocm_cmhdr.cmsg_len += cc;
}
msg -> msg_controllen = oc -> ocm_control.ocm_cmhdr.cmsg_len;
return sendmsg (fd, msg, 0);
}
STATIC int getCmsg(fd, cc, type, data)
int fd;
unsigned int *cc;
int *type;
char *data;
{
int result;
register struct msghdr *msg = &msgs;
register union osi_control_msg *oc = &ocm;
bzero ((char *) msg, sizeof *msg);
msg -> msg_control = oc -> ocm_data;
msg -> msg_controllen = sizeof oc -> ocm_data;
bzero ((char *) oc, sizeof *oc);
result = recvmsg (fd, msg, 0);
if (result >= 0 && cc && type && data) {
register int n =
(oc -> ocm_control.ocm_cmhdr.cmsg_len
- sizeof (oc -> ocm_control.ocm_cmhdr));
if (n > 0) {
*type = oc-> ocm_control.ocm_cmhdr.cmsg_type;
if (n > *cc)
n = *cc;
bcopy(oc -> ocm_control.ocm_cmdata, data, n);
*cc = n;
}
}
}
/* \f
UPPER HALF */
STATIC int TConnect (tb, expedited, data, cc, td)
register struct tsapblk *tb;
char *data;
int expedited,
cc;
struct TSAPdisconnect *td;
{
int len;
union sockaddr_osi sock;
struct sockaddr_iso *ifaddr = &sock.osi_sockaddr;
struct tp_conn_param tcp;
register struct tp_conn_param *p = &tcp;
if (gen2tp4 (&tb -> tb_responding, &sock) == NOTOK)
return tsaplose (td, DR_ADDRESS, NULLCP,
"unable to parse remote address");
len = sizeof *p;
if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p, &len)
== NOTOK)
SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ("unable to get"));
else {
if (p -> p_xpd_service ? !expedited : expedited) {
p -> p_xpd_service = expedited ? 1 : 0;
if (setsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS,
(char *) p, sizeof *p) == NOTOK)
SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS",
("unable to set"));
}
if (expedited)
tb -> tb_flags |= TB_EXPD;
if (p -> p_tpdusize > 0) {
if (p -> p_tpdusize > 10)
p -> p_tpdusize = 10;
tb -> tb_tpduslop = TP4SLOP;
tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop;
}
}
if (data &&
sendCmsg(tb->tb_fd, data, cc, TPOPT_CONN_DATA) == NOTOK)
return tsaplose (td, DR_CONGEST, "TPOPT_CONN_DATA", "unable to send");
/*
this is a real hack to pass information between TConnect and TRetry:
if tb_srcref is 0xffff: this indicates that the connect is still
in progress
if tb_srcref is 0xfffe: this indicates the connect is done
otherwise: this indicates a TS error
*/
if (connect (tb -> tb_fd, (struct sockaddr *) ifaddr, ifaddr -> siso_len)
== NOTOK) {
if (errno == EINPROGRESS) {
tb -> tb_srcref = 0xffff;
return CONNECTING_1;
}
if (!(errno & TP_ERROR_MASK))
return tsaplose (td, DR_REFUSED, "connection",
"unable to establish");
tb -> tb_srcref = (errno & ~TP_ERROR_MASK) & 0xff;
}
else
tb -> tb_srcref = 0xfffe;
return DONE;
}
/* \f
*/
STATIC int TRetry (tb, async, tc, td)
register struct tsapblk *tb;
int async;
struct TSAPconnect *tc;
struct TSAPdisconnect *td;
{
int len,
onoff,
flags,
reason;
union sockaddr_osi sock;
struct sockaddr_iso *ifaddr = &sock.osi_sockaddr;
struct tp_conn_param tcp;
int cmsgtype = 0;
register struct tp_conn_param *p = &tcp;
switch (tb -> tb_srcref) {
case 0xfffe:
reason = NOTOK;
break;
default:
reason = tb -> tb_srcref;
case 0xffff:
if (async)
switch ((*tb -> tb_retryfnx) (tb, td)) {
case NOTOK:
goto out;
case OK:
return CONNECTING_1;
case DONE:
break;
}
(void) gen2tp4 (&tb -> tb_responding, &sock);
if (connect (tb -> tb_fd, (struct sockaddr *) ifaddr,
ifaddr -> siso_len) == NOTOK)
switch (errno) {
case EINPROGRESS:
return CONNECTING_1;
case EISCONN:
reason = NOTOK;
break;
default:
/* for the moment, u.u_error limited to one byte */
/* this will be fixed real soon now. */
/* if (!(errno & TP_ERROR_MASK)) */
if (errno > 0) {
(void) tsaplose (td, DR_REFUSED, "connection",
"unable to establish");
goto out;
}
reason = (errno & ~TP_ERROR_MASK) & 0xff;
break;
}
break;
}
if (async)
(void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff));
if (reason == NOTOK) {
tc -> tc_sd = tb -> tb_fd;
tc -> tc_tsdusize = tb -> tb_tsdusize = MAXTP4;
len = sizeof sock;
if (getsockname (tb -> tb_fd, (struct sockaddr *) ifaddr, &len)
!= NOTOK) {
ifaddr -> siso_len = len;
(void) tp42gen (&tb -> tb_responding, &sock);
}
else
SLOG (tsap_log, LLOG_EXCEPTIONS, "failed", ("getpeername"));
tc -> tc_responding = tb -> tb_responding;
len = sizeof *p;
if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p,
&len)== NOTOK)
SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS",
("unable to get"));
else {
if (!p -> p_xpd_service)
tb -> tb_flags &= ~TB_EXPD;
if (p -> p_tpdusize > 0) {
if (p -> p_tpdusize > 10)
p -> p_tpdusize = 10;
tb -> tb_tpduslop = TP4SLOP;
tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop;
}
}
tc -> tc_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0;
tc -> tc_cc = sizeof tc -> tc_data;
if (getCmsg(tb->tb_fd, &cmsgtype, &tc->tc_cc, tc->tc_data) < 0) {
tc -> tc_cc = 0;
} else if (cmsgtype != TPOPT_CFRM_DATA)
tc -> tc_cc = 0;
tb -> tb_flags |= TB_CONN;
#ifdef MGMT
if (tb -> tb_manfnx)
(*tb -> tb_manfnx) (OPREQOUT, tb);
#endif
return DONE;
}
td -> td_reason = reason;
td -> td_cc = sizeof td -> td_data;
if (getCmsg(tb->tb_fd, &cmsgtype, &td->td_cc, td->td_data) < 0)
td -> td_cc = 0;
else if (cmsgtype != TPOPT_DISC_DATA)
td -> td_cc = 0;
out: ;
freetblk (tb);
return NOTOK;
}
/* \f
*/
STATIC int TStart (tb, cp, ts, td)
register struct tsapblk *tb;
char *cp;
struct TSAPstart *ts;
struct TSAPdisconnect *td;
{
int i,
len;
struct tp_conn_param tcp;
register struct tp_conn_param *p = &tcp;
len = sizeof *p;
if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p, &len)
== NOTOK)
SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ("unable to get"));
else {
if (p -> p_xpd_service)
tb -> tb_flags |= TB_EXPD;
if (p -> p_tpdusize > 0) {
if (p -> p_tpdusize > 10)
p -> p_tpdusize = 10;
tb -> tb_tpduslop = TP4SLOP;
tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop;
}
}
ts -> ts_sd = tb -> tb_fd;
ts -> ts_calling = tb -> tb_initiating; /* struct copy */
ts -> ts_called = tb -> tb_responding; /* struct copy */
ts -> ts_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0;
ts -> ts_tsdusize = tb -> tb_tsdusize;
if ((i = strlen (cp)) > 0) {
if (i > 2 * TS_SIZE)
return tsaplose (td, DR_CONNECT, NULLCP,
"too much initial user data");
ts -> ts_cc = implode ((u_char *) ts -> ts_data, cp, i);
}
else
ts -> ts_cc = 0;
return OK;
}
/* \f
*/
/* ARGSUSED */
STATIC int TAccept (tb, responding, data, cc, qos, td)
register struct tsapblk *tb;
char *data;
int responding,
cc;
struct QOStype *qos;
struct TSAPdisconnect *td;
{
int len;
struct tp_conn_param tcp;
register struct tp_conn_param *p = &tcp;
len = sizeof *p;
if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p, &len)
== NOTOK)
SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ("unable to get"));
else {
if (!p -> p_xpd_service)
tb -> tb_flags &= ~TB_EXPD;
else
if (!(tb -> tb_flags & TB_EXPD)) {
p -> p_xpd_service = 0;
if (setsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS,
(char *) p, sizeof *p) == NOTOK)
SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS",
("unable to set"));
}
if (p -> p_tpdusize > 0) {
if (p -> p_tpdusize > 10)
p -> p_tpdusize = 10;
tb -> tb_tpduslop = TP4SLOP;
tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop;
}
}
if (sendCmsg (tb -> tb_fd, cc, TPOPT_CFRM_DATA, data) == NOTOK)
return tsaplose (td, DR_CONGEST, "TPOPT_CFRM_DATA", "unable to send");
tb -> tb_flags |= TB_CONN;
#ifdef MGMT
if (tb -> tb_manfnx)
(*tb -> tb_manfnx) (OPREQIN, tb);
#endif
return OK;
}
/* \f
*/
/* life would be nice if we didn't have to worry about the maximum number of
bytes that can be written in a single syscall() */
#ifndef MSG_MAXIOVLEN
#define MSG_MAXIOVLEN NTPUV
#endif
STATIC int TWrite (tb, uv, expedited, td)
register struct tsapblk *tb;
register struct udvec *uv;
int expedited;
struct TSAPdisconnect *td;
{
register int cc;
int flags,
j,
len;
#ifdef MGMT
int dlen;
#endif
register char *bp,
*ep;
register struct qbuf *qb;
register struct msghdr *msg = &msgs;
struct iovec iovs[MSG_MAXIOVLEN];
register struct iovec *vv,
*wv;
bzero ((char *) msg, sizeof *msg);
flags = expedited ? MSG_OOB : 0;
#ifdef MGMT
dlen = 0;
#endif
if (!expedited && (tb -> tb_flags & TB_QWRITES)) {
int onoff,
nc;
struct udvec *xv;
cc = 0;
for (xv = uv; xv -> uv_base; xv++)
cc += xv -> uv_len;
#ifdef MGMT
dlen = cc;
#endif
if ((qb = (struct qbuf *) malloc (sizeof *qb + (unsigned) cc))
== NULL) {
(void) tsaplose (td, DR_CONGEST, NULLCP,
"unable to malloc %d octets for pseudo-writev, failing...",
cc);
freetblk (tb);
return NOTOK;
}
qb -> qb_forw = qb -> qb_back = qb;
qb -> qb_data = qb -> qb_base, qb -> qb_len = cc;
bp = qb -> qb_data;
for (xv = uv; xv -> uv_base; xv++) {
bcopy (xv -> uv_base, bp, xv -> uv_len);
bp += xv -> uv_len;
}
if (tb -> tb_qwrites.qb_forw != &tb -> tb_qwrites) {
nc = 0;
goto insert;
}
vv = iovs;
vv -> iov_base = qb -> qb_data, vv -> iov_len = qb -> qb_len;
vv++;
msg -> msg_iov = iovs;
msg -> msg_iovlen = vv - iovs;
(void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff));
nc = sendmsg (tb -> tb_fd, msg, MSG_EOR);
(void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff));
if (nc != cc) {
if (nc == NOTOK) {
if (errno != EWOULDBLOCK) {
(void) tsaplose (td, DR_CONGEST, "failed", "sendmsg");
goto losing;
}
nc = 0;
}
if ((*tb -> tb_queuePfnx) (tb, 1, td) == NOTOK)
goto losing;
qb -> qb_data += nc, qb -> qb_len -= nc;
insert: ;
insque (qb, tb -> tb_qwrites.qb_back);
DLOG (tsap_log, LLOG_TRACE,
("queueing blocked write of %d of %d octets", nc, cc));
}
else
free ((char *) qb);
goto done;
losing: ;
free ((char *) qb);
freetblk (tb);
return NOTOK;
}
ep = (bp = uv -> uv_base) + (cc = uv -> uv_len);
while (uv -> uv_base) {
wv = (vv = iovs) + MSG_MAXIOVLEN;
for (len = tb -> tb_tsdusize; len > 0 && vv < wv; len -= j) {
j = min (cc, len);
#ifdef MGMT
dlen += j;
#endif
vv -> iov_base = bp, vv -> iov_len = j, vv++;
bp += j, cc -= j;
if (bp >= ep) {
if ((bp = (++uv) -> uv_base) == NULL)
break;
ep = bp + (cc = uv -> uv_len);
}
}
if (expedited || uv -> uv_base == NULL)
flags |= MSG_EOR;
msg -> msg_iov = iovs;
msg -> msg_iovlen = vv - iovs;
if (sendmsg (tb -> tb_fd, msg, flags) == NOTOK) {
(void) tsaplose (td, DR_CONGEST, "failed", "sendmsg");
freetblk (tb);
return NOTOK;
}
}
done: ;
#ifdef MGMT
if (tb -> tb_manfnx)
(*tb -> tb_manfnx) (USERDT, tb, dlen);
#endif
return OK;
}
/* \f
*/
STATIC int TDrain (tb, td)
register struct tsapblk *tb;
struct TSAPdisconnect *td;
{
int nc,
onoff,
result;
register struct qbuf *qb;
register struct msghdr *msg = &msgs;
struct iovec vvs;
register struct iovec *vv = &vvs;
bzero ((char *) msg, sizeof *msg);
msg -> msg_iov = vv, msg -> msg_iovlen = 1;
(void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff));
while ((qb = tb -> tb_qwrites.qb_forw) != &tb -> tb_qwrites) {
vv -> iov_base = qb -> qb_data, vv -> iov_len = qb -> qb_len;
if (nc = sendmsg (tb -> tb_fd, msg, MSG_EOR) != qb -> qb_len) {
if (nc == NOTOK) {
if (errno != EWOULDBLOCK) {
result = tsaplose (td, DR_NETWORK, "failed",
"write to network");
goto out;
}
nc = 0;
}
qb -> qb_data += nc, qb -> qb_len -= nc;
DLOG (tsap_log, LLOG_TRACE,
("wrote %d of %d octets from blocked write", nc,
qb -> qb_len));
result = OK;
goto out;
}
DLOG (tsap_log, LLOG_TRACE,
("finished blocked write of %d octets", qb -> qb_len));
remque (qb);
free ((char *) qb);
}
result = DONE;
out: ;
(void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff));
return result;
}
/* \f
*/
/* ARGSUSED */
STATIC int TRead (tb, tx, td, async, oob)
register struct tsapblk *tb;
register struct TSAPdata *tx;
struct TSAPdisconnect *td;
int async,
oob;
{
int cc;
register struct qbuf *qb;
register struct msghdr *msg = &msgs;
register union osi_control_msg *oc = &ocm;
struct iovec iovs[1];
static struct qbuf *spare_qb = 0;
bzero ((char *) tx, sizeof *tx);
tx -> tx_qbuf.qb_forw = tx -> tx_qbuf.qb_back = &tx -> tx_qbuf;
for (;;) {
qb = NULL;
if (spare_qb) {
if (spare_qb -> qb_len >= tb -> tb_tsdusize)
qb = spare_qb;
else
free ((char *)spare_qb);
spare_qb = NULL;
}
if (qb == NULL && (qb = (struct qbuf *) malloc ((unsigned) (sizeof *qb
+ tb -> tb_tsdusize)))
== NULL) {
(void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
break;
}
qb -> qb_data = qb -> qb_base;
bzero ((char *) msg, sizeof *msg);
msg -> msg_iov = iovs;
msg -> msg_iovlen = 1;
msg -> msg_control = oc -> ocm_data;
msg -> msg_controllen = sizeof oc -> ocm_data;
iovs[0].iov_base = qb -> qb_data;
iovs[0].iov_len = tb -> tb_tsdusize;
bzero ((char *) oc, sizeof *oc);
if ((cc = recvmsg(tb -> tb_fd, msg, 0)) == NOTOK) {
/*if ((cc = recvmsg(tb -> tb_fd, msg, oob ? MSG_OOB : 0)) == NOTOK) */
if (!(errno & TP_ERROR_MASK)) {
(void) tsaplose (td, DR_CONGEST, "failed", "recvfrom");
break;
}
if ((td -> td_reason = errno & ~TP_ERROR_MASK) != DR_NORMAL)
SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
("TP error %d", td -> td_reason));
td -> td_cc = 0;
break;
}
if (msg -> msg_controllen) {
if (msg -> msg_controllen < sizeof oc -> ocm_control.ocm_cmhdr) {
(void) tsaplose (td, DR_CONGEST, NULLCP,
"truncated control message, got %d expecting at least %d",
msg -> msg_controllen,
sizeof oc -> ocm_control.ocm_cmhdr);
break;
}
if (oc -> ocm_control.ocm_cmhdr.cmsg_level != SOL_TRANSPORT
|| oc -> ocm_control.ocm_cmhdr.cmsg_type
!= TPOPT_DISC_DATA) {
(void) tsaplose (td, DR_CONGEST, NULLCP,
"unexpected message (level 0x%x, type 0x%x)",
oc -> ocm_control.ocm_cmhdr.cmsg_level,
oc -> ocm_control.ocm_cmhdr.cmsg_type);
break;
}
td -> td_reason = DR_NORMAL;
if ((td -> td_cc = oc -> ocm_control.ocm_cmhdr.cmsg_len
- sizeof oc -> ocm_control.ocm_cmhdr) > 0)
bcopy (oc -> ocm_control.ocm_cmdata, td -> td_data, cc);
break;
}
if (msg -> msg_flags & MSG_OOB) {
if (cc > 0) {
insque (qb, tx -> tx_qbuf.qb_back);
tx -> tx_cc = (qb -> qb_len = cc);
}
else
free ((char *) qb);
tx -> tx_expedited = 1;
return OK;
}
tb -> tb_len += (qb -> qb_len = cc);
if (cc > 0) {
register struct qbuf *qb2 = tb -> tb_qbuf.qb_back;
if (qb2 != &tb->tb_qbuf && qb2->qb_len + cc <= tb->tb_tsdusize) {
bcopy(qb -> qb_data, qb2 -> qb_len + qb2 -> qb_data, cc);
qb2 -> qb_len += cc;
(spare_qb = qb) -> qb_len = tb -> tb_tsdusize;
} else
insque (qb, qb2);
} else
free ((char *) qb);
#ifdef MGMT
if (tb -> tb_manfnx)
(*tb -> tb_manfnx) (USERDR, tb, tb -> tb_len);
#endif
if (!(msg -> msg_flags & MSG_EOR)) {
if (async) {
register struct qbuf *qb2 = tb -> tb_qbuf.qb_back;
if (qb2 != &tb->tb_qbuf && qb2->qb_len <= tb->tb_tsdusize)
printf("short return %d\n", qb2->qb_len);
return DONE;
}
continue;
}
tx -> tx_expedited = 0;
if (tb -> tb_qbuf.qb_forw != &tb -> tb_qbuf) {
tx -> tx_qbuf = tb -> tb_qbuf; /* struct copy */
tx -> tx_qbuf.qb_forw -> qb_back =
tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf;
tx -> tx_cc = tb -> tb_len;
tb -> tb_qbuf.qb_forw =
tb -> tb_qbuf.qb_back = &tb -> tb_qbuf;
tb -> tb_len = 0;
}
{
register struct qbuf *qb2 = tb -> tb_qbuf.qb_back;
if (qb2 != &tb->tb_qbuf && qb2->qb_len <= tb->tb_tsdusize)
printf("short return %d\n", qb2->qb_len);
}
return OK;
}
if (qb)
free ((char *) qb);
freetblk (tb);
return NOTOK;
}
/* \f
*/
STATIC int TDisconnect (tb, data, cc, td)
register struct tsapblk *tb;
char *data;
int cc;
struct TSAPdisconnect *td;
{
int result;
if (sendCmsg(tb -> tb_fd, cc, TPOPT_DISC_DATA, data) == NOTOK)
result = tsaplose (td, DR_CONGEST, "TPOPT_DISC_DATA",
"unable to send");
else
result = OK;
freetblk (tb);
return result;
}
/* \f
*/
/* ARGSUSED */
STATIC int TLose (tb, reason, td)
register struct tsapblk *tb;
int reason;
struct TSAPdisconnect *td;
{
register struct msghdr *msg = &msgs;
register union osi_control_msg *oc = &ocm;
SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("TPM error %d", reason));
bzero ((char *) msg, sizeof *msg);
msg -> msg_control = oc -> ocm_data;
msg -> msg_controllen = sizeof oc -> ocm_data;
bzero ((char *) oc, sizeof *oc);
oc -> ocm_control.ocm_cmhdr.cmsg_level = SOL_TRANSPORT;
oc -> ocm_control.ocm_cmhdr.cmsg_type = TPOPT_DISC_DATA;
oc -> ocm_control.ocm_cmhdr.cmsg_len = sizeof oc -> ocm_control.ocm_cmhdr;
if (sendmsg (tb -> tb_fd, msg, 0) == NOTOK)
SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_DISC_DATA",
("unable to send"));
}
/* \f
LOWER HALF */
/* ARGSUSED */
int tp4open (tb, local_ta, local_na, remote_ta, remote_na, td, async)
register struct tsapblk *tb;
struct TSAPaddr *local_ta,
*remote_ta;
struct NSAPaddr *local_na,
*remote_na;
struct TSAPdisconnect *td;
int async;
{
int fd,
onoff;
struct TSAPaddr tzs;
register struct TSAPaddr *tz = &tzs;
register struct NSAPaddr *nz = tz -> ta_addrs;
union sockaddr_osi sock;
struct sockaddr_iso *ifaddr = &sock.osi_sockaddr;
bzero ((char *) tz, sizeof *tz);
if (local_ta)
*tz = *local_ta; /* struct copy */
if (local_na) {
*nz = *local_na; /* struct copy */
tz -> ta_naddr = 1;
}
(void) gen2tp4 (tz, &sock);
if ((fd = socket (AF_ISO, SOCK_SEQPACKET, 0)) == NOTOK)
return tsaplose (td, DR_CONGEST, "socket", "unable to start");
if (ifaddr->siso_nlen || ifaddr->siso_tlen)
if (bind (fd, (struct sockaddr *) ifaddr, ifaddr -> siso_len) == NOTOK) {
(void) tsaplose (td, DR_ADDRESS, "socket", "unable to bind");
(void) close (fd);
return NOTOK;
}
tb -> tb_fd = fd;
(void) tp4init (tb);
if (async)
(void) ioctl (fd, FIONBIO, (onoff = 1, (char *) &onoff));
return (async ? OK : DONE);
}
/* \f
*/
/* ARGSUSED */
STATIC int retry_tp4_socket (tb, td)
register struct tsapblk *tb;
struct TSAPdisconnect *td;
{
fd_set mask;
FD_ZERO (&mask);
FD_SET (tb -> tb_fd, &mask);
if (xselect (tb -> tb_fd + 1, NULLFD, &mask, NULLFD, 0) < 1)
return OK;
return DONE;
}
/* \f
*/
/* ARGSUSED */
char *tp4save (fd, td)
int fd;
struct TSAPdisconnect *td;
{
static char buffer[BUFSIZ];
(void) sprintf (buffer, "%c%d", NT_BSD, fd);
return buffer;
}
/* \f
*/
int tp4restore (tb, buffer, td)
register struct tsapblk *tb;
char *buffer;
struct TSAPdisconnect *td;
{
int fd;
int len;
union sockaddr_osi sock;
struct sockaddr_iso *ifaddr = &sock.osi_sockaddr;
if (sscanf (buffer, "%d", &fd) != 1 || fd < 0)
return tsaplose (td, DR_PARAMETER, NULLCP,
"bad initialization vector \"%s\"", buffer);
tb -> tb_fd = fd;
(void) tp4init (tb);
len = sizeof sock;
if (getsockname (fd, (struct sockaddr *) ifaddr, &len) == NOTOK) {
(void) tsaplose (td, DR_CONGEST, "listen",
"getsockname failed for tp4restore");
(void) close (fd);
return NOTOK;
}
ifaddr -> siso_len = len;
(void) tp42gen (&tb->tb_responding, &sock);
len = sizeof sock;
if (getpeername (fd, (struct sockaddr *) ifaddr, &len) == NOTOK) {
(void) tsaplose (td, DR_CONGEST, "listen",
"getpeername failed for tp4restore");
(void) close (fd);
return NOTOK;
}
ifaddr -> siso_len = len;
(void) tp42gen (&tb->tb_initiating, &sock);
return OK;
}
/* \f
*/
int tp4init (tb)
register struct tsapblk *tb;
{
tb -> tb_connPfnx = TConnect;
tb -> tb_retryPfnx = TRetry;
tb -> tb_startPfnx = TStart;
tb -> tb_acceptPfnx = TAccept;
tb -> tb_writePfnx = TWrite;
tb -> tb_readPfnx = TRead;
tb -> tb_discPfnx = TDisconnect;
tb -> tb_losePfnx = TLose;
tb -> tb_drainPfnx = TDrain;
#ifdef MGMT
tb -> tb_manfnx = TManGen;
#endif
tb -> tb_flags |= TB_TP4;
tb -> tb_tsdusize = MAXTP4 - (tb -> tb_tpduslop = 0);
tb -> tb_retryfnx = retry_tp4_socket;
tb -> tb_closefnx = close_tp4_socket;
tb -> tb_selectfnx = select_tp4_socket;
}
/* \f
*/
/* ARGSUSED */
int start_tp4_server (local_ta, backlog, opt1, opt2, td)
struct TSAPaddr *local_ta;
int backlog,
opt1,
opt2;
struct TSAPdisconnect *td;
{
int sd,
onoff;
register struct NSAPaddr *na = local_ta -> ta_addrs;
union sockaddr_osi sock;
struct sockaddr_iso *ifaddr = &sock.osi_sockaddr;
(void) gen2tp4 (local_ta, &sock);
if ((sd = socket (AF_ISO, SOCK_SEQPACKET, 0)) == NOTOK)
return tsaplose (td, DR_CONGEST, "socket", "unable to start");
if (bind (sd, (struct sockaddr *) ifaddr, ifaddr -> siso_len) == NOTOK) {
(void) tsaplose (td, DR_ADDRESS, "socket", "unable to bind");
(void) close (sd);
return NOTOK;
}
if (na -> na_addrlen == 0) { /* unique listen */
int len;
len = sizeof sock;
if (getsockname (sd, (struct sockaddr *) ifaddr, &len) == NOTOK) {
(void) tsaplose (td, DR_CONGEST, "listen",
"getsockname failed for unique");
(void) close (sd);
return NOTOK;
}
ifaddr -> siso_len = len;
(void) tp42gen (local_ta, &sock);
}
if (opt1)
(void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0);
if (opt2)
(void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0);
onoff = 1;
if (setsockopt (sd, SOL_TRANSPORT, TPOPT_NGC8_ACCEPT, (caddr_t) &onoff,
sizeof onoff) == NOTOK) {
(void) tsaplose (td, DR_CONGEST, "TPOPT_NGC8_ACCEPT", "unable to set");
(void) close (sd);
return NOTOK;
}
(void) listen (sd, backlog);
return sd;
}
/* \f
*/
int join_tp4_client (fd, remote_ta, td)
int fd;
struct TSAPaddr *remote_ta;
struct TSAPdisconnect *td;
{
int len,
sd;
union sockaddr_osi sock;
struct sockaddr_iso *ifaddr = &sock.osi_sockaddr;
len = sizeof sock;
if ((sd = accept (fd, (struct sockaddr *) ifaddr, &len)) == NOTOK)
return tsaplose (td, DR_NETWORK, "socket", "unable to accept");
ifaddr -> siso_len = len;
(void) tp42gen (remote_ta, &sock);
return sd;
}
/* \f
*/
int gen2tp4 (generic, specific)
struct TSAPaddr *generic;
union sockaddr_osi *specific;
{
register char *cp;
struct sockaddr_iso *ifaddr = &specific -> osi_sockaddr;
bzero ((char *) specific, sizeof *specific);
cp = ifaddr -> siso_data;
if (generic -> ta_naddr > 0) {
register struct NSAPaddr *na = generic -> ta_addrs;
if (ifaddr -> siso_nlen = na -> na_addrlen) {
bcopy (na -> na_address, cp, na -> na_addrlen);
cp += na -> na_addrlen;
}
}
if (ifaddr -> siso_tlen = generic -> ta_selectlen) {
bcopy (generic -> ta_selector, cp, generic -> ta_selectlen);
cp += generic -> ta_selectlen;
}
if ((ifaddr -> siso_len = cp - (char *) ifaddr) < sizeof *ifaddr)
ifaddr -> siso_len = sizeof *ifaddr;
ifaddr -> siso_family = AF_ISO;
return OK;
}
/* \f
*/
int tp42gen (generic, specific)
struct TSAPaddr *generic;
union sockaddr_osi *specific;
{
register char *cp;
register struct NSAPaddr *na = generic -> ta_addrs;
struct sockaddr_iso *ifaddr = &specific -> osi_sockaddr;
bzero ((char *) generic, sizeof *generic);
cp = ifaddr -> siso_data;
if (na -> na_addrlen = ifaddr -> siso_nlen) {
na -> na_type = NA_NSAP;
na -> na_subnet = ts_comm_nsap_default;
bcopy (cp, na -> na_address, na -> na_addrlen);
cp += na -> na_addrlen;
generic -> ta_naddr++;
}
if (generic -> ta_selectlen = ifaddr -> siso_tlen)
bcopy (cp, generic -> ta_selector, generic -> ta_selectlen);
return OK;
}
#endif