/* ts2sunlink.c - TPM: SunLink OSI TP4 interface */
static char *rcsid
= "$Header: /f/osi/tsap/RCS/ts2sunlink.c,v 7.13 91/03/09 11:58:19 mrose Exp $";
* $Header: /f/osi/tsap/RCS/ts2sunlink.c,v 7.13 91/03/09 11:58:19 mrose Exp $
* Contributed by John A. Scott, The MITRE Corporation
* Revision 7.13 91/03/09 11:58:19 mrose
* Revision 7.12 91/02/22 09:47:20 mrose
* Revision 7.11 91/01/14 13:34:30 mrose
* Revision 7.10 90/11/21 11:31:29 mrose
* Revision 7.9 90/11/11 10:48:07 mrose
* Revision 7.8 90/07/09 14:51:17 mrose
* Revision 7.7 90/03/23 17:31:22 mrose
* Revision 7.6 90/03/22 08:38:08 mrose
* Revision 7.5 90/01/27 10:27:39 mrose
* Revision 7.4 89/12/19 10:18:38 mrose
* Revision 7.3 89/12/13 07:05:45 mrose
* Revision 7.2 89/12/08 09:41:35 mrose
* Revision 7.1 89/12/07 22:15:30 mrose
* Revision 7.0 89/11/23 22:30:38 mrose
* 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
#define MAXTP4 (1 << SIZE_8K)
#define OSI_AF_GENERIC AF_GENERIC
#define MSG_OSI_OOB MSG_OOB
/* A driver for SunLink OSI's TP4!
* SunLink OSI TP4 user interface is very much like a ``datagram''
* interface. Some of the hair in this port involves converting
* ISODE TP packets into SUN TP4 packets. My gut feeling is that the
* port should be redone to make better use of existing ISODE
* structures (but this works and I hesitate to change something works).
* Actually, I think is fairly close to optimal now.
* 1. Figure out how to implement tsaplisten.c$tp4unique()
* 2. On failure of sendto, sendmsg, or recvfrom, try to figure out if a
* disconnect happened and return the right DR_ reason.
* 3. SunLink OSI should support TSELs of length greater than two. In fact,
* a transport address really should be:
* nsap - 64 octets, tsel - 44 octets (would prefer 64, but mbufs limit)
* 4. Should do QOS mappings for error recovery (not class 0 or 2) and cost
static int TConnect (tb
, expedited
, data
, cc
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct tp4pkt
*t
;
if ((t
= newtp4pkt (TP_CONNECT_REQ
)) == NULL
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
if (gen2tp4X (&tb
-> tb_responding
, &t
-> tp4_called
,
tb
-> tb_initiating
.ta_present
? &tb
-> tb_initiating
.ta_addr
: NULLNA
) == NOTOK
) {
result
= tsaplose (td
, DR_ADDRESS
, NULLCP
,
"unable to parse remote address");
if (gen2tp4X (&tb
-> tb_initiating
, &t
-> tp4_calling
,
tb
-> tb_responding
.ta_present
? &tb
-> tb_responding
.ta_addr
: NULLNA
) == NOTOK
) {
result
= tsaplose (td
, DR_ADDRESS
, NULLCP
,
"unable to parse local address");
tb
-> tb_flags
|= TB_EXPD
;
if (sendto (tb
-> tb_fd
, data
, cc
, 0, (struct sockaddr
*) t
,
sizeof (TP_MSG_CONNECT
)) == NOTOK
)
result
= tsaplose (td
, DR_CONGEST
, "failed", "sendto");
static int TRetry (tb
, async
, tc
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct tp4pkt
*t
;
switch ((*tb
-> tb_retryfnx
) (tb
, td
)) {
if ((t
= newtp4pkt ((TP_EVENT
) 0)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
header_len
= sizeof (TP_MSG_CONNECT
);
if ((cc
= recvfrom (tb
-> tb_fd
, data
, sizeof data
, 0,
(struct sockaddr
*) t
, &header_len
)) == NOTOK
) {
if (errno
== EWOULDBLOCK
) {
(void) tsaplose (td
, DR_CONGEST
, "failed", "recvfrom");
(void) ioctl (tb
-> tb_fd
, FIONBIO
, (onoff
= 0, (char *) &onoff
));
switch (t
-> tp4_event
) {
tc
-> tc_sd
= tb
-> tb_fd
;
tc
-> tc_tsdusize
= tb
-> tb_tsdusize
= MAXTP4
;
(void) tp42genX (&tb
-> tb_responding
, &t
-> tp4_calling
);
copyTSAPaddrX (&tb
-> tb_responding
, &tc
-> tc_responding
);
if ((tb
-> tb_flags
& TB_EXPD
) && !t
-> tp4_expedited
)
tb
-> tb_flags
&= ~TB_EXPD
;
tc
-> tc_expedited
= (tb
-> tb_flags
& TB_EXPD
) ? 1 : 0;
if ((tc
-> tc_cc
= cc
) > 0)
bcopy (data
, tc
-> tc_data
, cc
);
tb
-> tb_flags
|= TB_CONN
;
(*tb
-> tb_manfnx
) (OPREQOUT
, tb
);
free ((char *) tb
-> tb_calling
), tb
-> tb_calling
= NULL
;
free ((char *) tb
-> tb_called
), tb
-> tb_called
= NULL
;
if ((td
-> td_reason
= (int) t
-> tp4_reason
) == DR_UNKNOWN
)
td
-> td_reason
= DR_NETWORK
;
if ((td
-> td_cc
= cc
) > 0)
bcopy (data
, td
-> td_data
, cc
);
(void) tsaplose (td
, DR_NETWORK
, NULLCP
,
"expecting 0x%x, got 0x%x",
TP_CONNECT_CONF
, t
-> tp4_event
);
static int TStart (tb
, cp
, ts
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct tp4pkt
*tp
;
if ((i
= strlen (cp
)) < (cc
= 2 * sizeof (TP_MSG_CONNECT
)))
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"bad initialization vector");
if ((tp
= newtp4pkt ((TP_EVENT
) 0)) == NULL
) {
result
= tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
cc
= 2 * implode ((u_char
*) tp
, cp
, cc
);
tb
-> tb_flags
|= TB_EXPD
;
(void) tp42genX (&tb
-> tb_initiating
, &tp
-> tp4_calling
);
(void) tp42genX (&tb
-> tb_responding
, &tp
-> tp4_called
);
ts
-> ts_sd
= tb
-> tb_fd
;
copyTSAPaddrX (&tb
-> tb_initiating
, &ts
-> ts_calling
);
copyTSAPaddrX (&tb
-> tb_responding
, &ts
-> ts_called
);
ts
-> ts_expedited
= (tb
-> tb_flags
& TB_EXPD
) ? 1 : 0;
ts
-> ts_tsdusize
= tb
-> tb_tsdusize
;
result
= tsaplose (td
, DR_CONNECT
, NULLCP
,
"too much initial user data");
ts
-> ts_cc
= implode ((u_char
*) ts
-> ts_data
, cp
, i
);
static int TAccept (tb
, responding
, data
, cc
, qos
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct tp4pkt
*tp
;
if ((tp
= newtp4pkt (TP_CONNECT_RESP
)) == NULL
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
(void) gen2tp4X (&tb
-> tb_responding
, &tp
-> tp4_called
,
tb
-> tb_initiating
.ta_present
? &tb
-> tb_initiating
.ta_addr
: NULLNA
);
if (tb
-> tb_flags
& TB_EXPD
)
pstat
= signal (SIGPIPE
, SIG_IGN
);
if (sendto (tb
-> tb_fd
, data
, cc
, 0, (struct sockaddr
*) tp
,
sizeof (TP_MSG_CONNECT
)) == NOTOK
)
result
= ReadDisc(tb
, td
);
result
= tsaplose (td
, DR_CONGEST
, "failed", "sendto");
tb
-> tb_flags
|= TB_CONN
;
(*tb
-> tb_manfnx
) (OPREQIN
, tb
);
(void) signal (SIGPIPE
, pstat
);
/* 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() */
#define MSG_MAXIOVLEN NTPUV
static int TWrite (tb
, uv
, expedited
, td
)
register struct tsapblk
*tb
;
register struct udvec
*uv
;
struct TSAPdisconnect
*td
;
register struct msghdr
*msg
= &msgs
;
register struct tp4pkt
*tp
;
struct iovec iovs
[MSG_MAXIOVLEN
];
register struct iovec
*vv
,
if ((tp
= newtp4pkt (expedited
? TP_X_DATA_REQ
: TP_DATA_REQ
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
size
= sizeof (TP_MSG_X_DATA
), flags
= MSG_OOB
;
size
= sizeof (TP_MSG_DATA
), flags
= 0;
if (!expedited
&& (tb
-> tb_flags
& TB_QWRITES
)) {
register struct qbuf
*qb
;
for (xv
= uv
; xv
-> uv_base
; xv
++)
if ((qb
= (struct qbuf
*) malloc (sizeof *qb
+ (unsigned) cc
))
(void) tsaplose (td
, DR_CONGEST
, NULLCP
,
"unable to malloc %d octets for pseudo-writev, failing...",
qb
-> qb_forw
= qb
-> qb_back
= qb
;
qb
-> qb_data
= qb
-> qb_base
, qb
-> qb_len
= cc
;
for (xv
= uv
; xv
-> uv_base
; xv
++) {
bcopy (xv
-> uv_base
, bp
, xv
-> uv_len
);
if (tb
-> tb_qwrites
.qb_forw
!= &tb
-> tb_qwrites
) {
vv
-> iov_base
= qb
-> qb_data
, vv
-> iov_len
= qb
-> qb_len
;
msg
-> msg_name
= (caddr_t
) tp
;
msg
-> msg_namelen
= size
;
msg
-> msg_iovlen
= vv
- iovs
;
msg
-> msg_accrights
= (caddr_t
) NULL
;
msg
-> msg_accrightslen
= 0;
pstat
= signal (SIGPIPE
, SIG_IGN
);
(void) ioctl (tb
-> tb_fd
, FIONBIO
, (onoff
= 1, (char *) &onoff
));
nc
= sendmsg (tb
-> tb_fd
, msg
, flags
);
(void) ioctl (tb
-> tb_fd
, FIONBIO
, (onoff
= 0, (char *) &onoff
));
(void) signal (SIGPIPE
, pstat
);
if (errno
!= EWOULDBLOCK
) {
(void) tsaplose (td
, DR_CONGEST
, "failed", "sendmsg");
if ((*tb
-> tb_queuePfnx
) (tb
, 1, td
) == NOTOK
)
qb
-> qb_data
+= nc
, qb
-> qb_len
-= nc
;
insque (qb
, tb
-> tb_qwrites
.qb_back
);
DLOG (tsap_log
, LLOG_TRACE
,
("queueing blocked write of %d of %d octets", nc
, cc
));
pstat
= signal (SIGPIPE
, SIG_IGN
);
ep
= (bp
= uv
-> uv_base
) + (cc
= uv
-> uv_len
);
wv
= (vv
= iovs
) + MSG_MAXIOVLEN
;
for (len
= tb
-> tb_tsdusize
; len
> 0 && vv
< wv
; len
-= j
) {
vv
-> iov_base
= bp
, vv
-> iov_len
= j
, vv
++;
if ((bp
= (++uv
) -> uv_base
) == NULL
)
ep
= bp
+ (cc
= uv
-> uv_len
);
tp
-> tp4_eot
= uv
-> uv_base
== NULL
;
for (wv
= iovs
; wv
< vv
; wv
++) {
bcopy (wv
-> iov_base
, dp
, wv
-> iov_len
);
dp
+= wv
-> iov_len
, len
+= wv
-> iov_len
;
vv
-> iov_base
= data
, vv
-> iov_len
= len
, vv
++;
msg
-> msg_name
= (caddr_t
) tp
;
msg
-> msg_namelen
= size
;
msg
-> msg_iovlen
= vv
- iovs
;
msg
-> msg_accrights
= (caddr_t
) NULL
;
msg
-> msg_accrightslen
= 0;
if (sendmsg (tb
-> tb_fd
, msg
, flags
) == NOTOK
) {
(void) signal (SIGPIPE
, pstat
);
(void) tsaplose (td
, DR_CONGEST
, "failed", "sendmsg");
(void) signal (SIGPIPE
, pstat
);
(*tb
-> tb_manfnx
) (USERDT
, tb
, dlen
);
static int TDrain (tb
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct qbuf
*qb
;
register struct msghdr
*msg
= &msgs
;
register struct tp4pkt
*tp
;
register struct iovec
*vv
= &vvs
;
if ((tp
= newtp4pkt (TP_DATA_REQ
)) == NULL
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
msg
-> msg_name
= (caddr_t
) tp
;
msg
-> msg_namelen
= sizeof (TP_MSG_DATA
);
msg
-> msg_iov
= vv
, msg
-> msg_iovlen
= 1;
msg
-> msg_accrights
= (caddr_t
) NULL
;
msg
-> msg_accrightslen
= 0;
pstat
= signal (SIGPIPE
, SIG_IGN
);
(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
, 0) != qb
-> qb_len
) {
result
= ReadDisc(tb
, td
);
if (errno
!= EWOULDBLOCK
) {
result
= tsaplose (td
, DR_NETWORK
, "failed",
DLOG (tsap_log
, LLOG_TRACE
,
("wrote %d of %d octets from blocked write", nc
,
qb
-> qb_data
+= nc
, qb
-> qb_len
-= nc
;
DLOG (tsap_log
, LLOG_TRACE
,
("finished blocked write of %d octets", qb
-> qb_len
));
(void) ioctl (tb
-> tb_fd
, FIONBIO
, (onoff
= 0, (char *) &onoff
));
(void) sigiomask (smask
);
(void) signal (SIGPIPE
, pstat
);
static int TRead (tb
, tx
, td
, async
, oob
)
register struct tsapblk
*tb
;
register struct TSAPdata
*tx
;
struct TSAPdisconnect
*td
;
register struct qbuf
*qb
;
register struct tp4pkt
*tp
;
bzero ((char *) tx
, sizeof *tx
);
tx
-> tx_qbuf
.qb_forw
= tx
-> tx_qbuf
.qb_back
= &tx
-> tx_qbuf
;
if ((qb
= (struct qbuf
*) malloc ((unsigned) (sizeof *qb
+ sizeof *tp
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
tp
= (struct tp4pkt
*) qb
-> qb_base
;
qb
-> qb_data
= qb
-> qb_base
+ sizeof *tp
;
header_len
= sizeof (struct tp4pkt
);
if ((cc
= recvfrom (tb
-> tb_fd
, qb
-> qb_data
, tb
-> tb_tsdusize
,
(struct sockaddr
*) tp
, &header_len
)) == NOTOK
) {
(void) tsaplose (td
, DR_CONGEST
, "failed", "recvfrom");
switch (tp
-> tp4_event
) {
insque (qb
, tb
-> tb_qbuf
.qb_back
);
tb
-> tb_len
+= (qb
-> qb_len
= cc
);
(*tb
-> tb_manfnx
) (USERDR
, tb
, tb
-> tb_len
);
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_back
= &tb
-> tb_qbuf
;
insque (qb
, tx
-> tx_qbuf
.qb_back
);
tx
-> tx_cc
= (qb
-> qb_len
= cc
);
td
-> td_reason
= (int) tp
-> tp4_reason
;
if ((td
-> td_cc
= cc
) > 0)
bcopy (qb
-> qb_data
, td
-> td_data
, cc
);
(void) tsaplose (td
, DR_NETWORK
, NULLCP
,
"unexpected response 0x%x",
(int) (tp
-> tp4_event
));
static int ReadDisc(tb
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
TP_MSG_DISCONNECT tps
, *tp
= &tps
;
int header_len
= sizeof (*tp
);
if ((cc
= recvfrom(tb
->tb_fd
, td
->td_data
, sizeof(td
->td_data
),
(struct sockaddr
*) tp
, &header_len
)) == NOTOK
) {
(void) tsaplose (td
, DR_CONGEST
, "failed", "recvfrom");
} else if (tp
-> tp_event
!= TP_DISCONNECT_IND
) {
(void) tsaplose (td
, DR_NETWORK
, NULLCP
,
"unexpected non-DR 0x%x",
td
-> td_reason
= (int) tp
-> reason
;
static int TDisconnect (tb
, data
, cc
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct tp4pkt
*tp
;
if (tp
= newtp4pkt (TP_DISCONNECT_REQ
)) {
tp
-> tp4_reason
= (TP_DR_REASON
) DR_NORMAL
;
pstat
= signal (SIGPIPE
, SIG_IGN
);
if (sendto (tb
-> tb_fd
, data
, cc
, 0, (struct sockaddr
*) tp
,
sizeof (TP_MSG_DISCONNECT
)) == NOTOK
)
result
= ReadDisc(tb
, td
);
result
= tsaplose (td
, DR_CONGEST
, "failed", "sendto");
(void) signal (SIGPIPE
, pstat
);
result
= tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
static int TLose (tb
, reason
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct tp4pkt
*tp
;
SLOG (tsap_log
, LLOG_EXCEPTIONS
, NULLCP
, ("TPM error %d", reason
));
if (tp
= newtp4pkt (TP_DISCONNECT_REQ
)) {
tp
-> tp4_reason
= (TP_DR_REASON
) reason
;
(void) sendto (tb
-> tb_fd
, NULLCP
, 0, 0, (struct sockaddr
*) tp
,
sizeof (TP_MSG_DISCONNECT
));
int tp4open (tb
, local_ta
, local_na
, remote_ta
, remote_na
, td
, async
)
register struct tsapblk
*tb
;
struct TSAPaddr
*local_ta
,
struct NSAPaddr
*local_na
,
struct TSAPdisconnect
*td
;
register struct TSAPaddr
*tz
= &tzs
;
register struct NSAPaddr
*nz
= tz
-> ta_addrs
;
bzero ((char *) tz
, sizeof *tz
);
*tz
= *local_ta
; /* struct copy */
*nz
= *local_na
; /* struct copy */
(void) gen2tp4 (tz
, &ifaddr
, remote_na
);
if ((fd
= socket (AF_OSI
, SOCK_EVENT
, OSIPROTO_TP_EVENT
)) == NOTOK
)
return tsaplose (td
, DR_CONGEST
, "socket", "unable to start");
if (bind (fd
, (struct sockaddr
*) &ifaddr
, sizeof ifaddr
) == NOTOK
) {
(void) tsaplose (td
, DR_ADDRESS
, "socket", "unable to bind");
(void) ioctl (fd
, FIONBIO
, (onoff
= 1, (char *) &onoff
));
return (async
? OK
: DONE
);
static int retry_tp4_socket (tb
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
FD_SET (tb
-> tb_fd
, &mask
);
if (xselect (tb
-> tb_fd
+ 1, &mask
, NULLFD
, NULLFD
, 0) < 1)
struct TSAPdisconnect
*td
;
static char buffer
[BUFSIZ
];
(void) sprintf (buffer
, "%c%d", NT_SUN
, fd
);
int tp4restore (tb
, buffer
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
if (sscanf (buffer
, "%d", &fd
) != 1 || fd
< 0)
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"bad initialization vector \"%s\"", buffer
);
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
;
tb
-> tb_manfnx
= TManGen
;
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
;
int start_tp4_server (sock
, backlog
, opt1
, opt2
, td
)
struct TSAPdisconnect
*td
;
(void) gen2tp4 (sock
, &ifaddr
, NULLNA
);
if ((sd
= socket (AF_OSI
, SOCK_EVENT
, OSIPROTO_TP_EVENT
)) == NOTOK
)
return tsaplose (td
, DR_CONGEST
, "socket", "unable to start");
if (bind (sd
, (struct sockaddr
*) &ifaddr
, sizeof ifaddr
) == NOTOK
) {
(void) tsaplose (td
, DR_ADDRESS
, "socket", "unable to bind");
if (listen (sd
, backlog
) == NOTOK
) {
(void) tsaplose (td
, DR_ADDRESS
, "listen", "");
int join_tp4_client (fd
, sock
, td
)
struct TSAPdisconnect
*td
;
if ((sd
= accept (fd
, (struct sockaddr
*) &ifaddr
, &len
)) == NOTOK
)
return tsaplose (td
, DR_NETWORK
, "socket", "unable to accept");
/* Ouch!! Trying to get the remote address off the socket
* only works for local connections. Non-local connections
* causes a core dump when I try to convert.
(void) tp42gen (sock
, &ifaddr
);
/* SunLink OSI address encoding/decoding */
static int gen2tp4 (generic
, specific
, template)
struct TSAPaddr
*generic
;
struct NSAPaddr
*template;
OSI_ADDR_INIT (specific
);
if (generic
-> ta_naddr
> 0) {
na
= generic
-> ta_addrs
;
paddr_type
= AF_OSI
, len
= 0;
if (na
-> na_addrlen
> 0)
switch (na
-> na_address
[0]) {
|| na
-> na_address
[1] != 0x00
|| na
-> na_address
[2] != 0x04)
osi_set_sap (na
-> na_address
+ len
, na
-> na_addrlen
- len
, specific
,
osi_set_sap (na
-> na_address
, na
-> na_addrlen
, specific
,
OSI_NSAP
, OSI_AF_USER_DEFINED
);
/* The SunLink OSI I'm using seems to require something
* although the ``manual'' says I don't. Hmmmm, I wonder
* if I still need the OSI_ADDR_INIT? BTW, osi_set_sap is one
* of the two functions I link from the -losi library. When I
* get the source for SunLink (maybe before I retire) I'll
* write my own set/get sap function and punt libosi.a
if (template != NULLNA
&& template -> na_addrlen
> 0)
switch (template -> na_address
[0]) {
if (template -> na_addrlen
< 3
|| template -> na_address
[1] != 0x00
|| template -> na_address
[2] != 0x04)
buffer
[0] = 0x00, len
= 1;
osi_set_sap (buffer
, len
, specific
, OSI_NSAP
, paddr_type
);
mds_lookup ("localhost", "CLIENT", specific
);;
osi_set_sap (generic
-> ta_selector
, generic
-> ta_selectlen
, specific
,
OSI_TSAP
, OSI_AF_GENERIC
);
static int gen2tp4X (generic
, specific
, template)
struct tsapADDR
*generic
;
struct NSAPaddr
*template;
copyTSAPaddrX (generic
, &tas
);
return gen2tp4 (&tas
, specific
, template);
int tp42gen (generic
, specific
)
struct TSAPaddr
*generic
;
if ((len
= osi_get_sap (specific
, buffer
, sizeof buffer
, OSI_NSAP
,
na
= generic
-> ta_addrs
;
na
-> na_stack
= NA_NSAP
;
na
-> na_community
= ts_comm_nsap_default
;
na
-> na_address
[0] = 0x49;
na
-> na_address
[0] = 0x47;
na
-> na_address
[1] = 0x00;
na
-> na_address
[2] = 0x04;
bcopy (buffer
, na
-> na_address
+ na
-> na_addrlen
, len
);
generic
-> ta_selectlen
= osi_get_sap (specific
, generic
-> ta_selector
,
TSSIZE
, OSI_TSAP
, &paddr_type
);
int tp42genX (generic
, specific
)
struct tsapADDR
*generic
;
if ((result
= tp42gen (&tas
, specific
)) == OK
)
copyTSAPaddrY (&tas
, generic
);
struct tp4pkt
*newtp4pkt (code
)
tp
= (struct tp4pkt
*) calloc (1, sizeof *tp
);
int _ts2sunlink_stub () {};