|
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: 9189 (0x23e5) Types: TextFile Names: »ts2tcp.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/tsap/ts2tcp.c«
/* ts2tcp.c - TPM: TCP interface */ #ifndef lint static char *rcsid = "$Header: /f/osi/tsap/RCS/ts2tcp.c,v 6.0 89/03/18 23:45:22 mrose Rel $"; #endif /* * $Header: /f/osi/tsap/RCS/ts2tcp.c,v 6.0 89/03/18 23:45:22 mrose Rel $ * * * $Log: ts2tcp.c,v $ * Revision 6.0 89/03/18 23:45:22 mrose * Release 5.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" #include "tailor.h" #ifdef TCP #include "internet.h" #include <errno.h> #ifdef BSD42 #include <sys/ioctl.h> #include <sys/time.h> #endif #ifdef WRITEV #include <sys/uio.h> #endif /* \f DATA */ #ifdef FIONBIO #define NODELAY #endif #ifdef NODELAY static fd_set inprogress; static struct sockaddr_in *peers = NULL; #endif extern int errno; /* \f N-CONNECT.REQUEST */ int tcpopen (tb, local, remote, td, async) register struct tsapblk *tb; struct NSAPaddr *local, *remote; struct TSAPdisconnect *td; int async; { int fd; #ifdef FIONBIO int onoff; #endif struct sockaddr_in lo_socket, in_socket; register struct sockaddr_in *lsock = &lo_socket, *isock = &in_socket; register struct hostent *hp; register struct servent *sp; #ifndef NODELAY if (async) return tsaplose (td, DR_PARAMETER, NULLCP, "asynchronous not supported"); #endif bzero ((char *) isock, sizeof *isock); if (remote -> na_port == 0) { if ((sp = getservbyname ("tsap", "tcp")) == NULL) return tsaplose (td, DR_ADDRESS, NULLCP, "tcp/tsap: unknown service"); isock -> sin_port = sp -> s_port; } else isock -> sin_port = remote -> na_port; if ((hp = gethostbystring (remote -> na_domain)) == NULL) return tsaplose (td, DR_ADDRESS, NULLCP, "%s: unknown host", remote -> na_domain); (void) strncpy (remote -> na_domain, hp -> h_name, sizeof remote -> na_domain); isock -> sin_family = hp -> h_addrtype; inaddr_copy (hp, isock); if (local && local -> na_domain[0]) { bzero ((char *) lsock, sizeof *lsock); if ((hp = gethostbystring (local -> na_domain)) == NULL) return tsaplose (td, DR_ADDRESS, NULLCP, "%s: unknown host", local -> na_domain); if ((lsock -> sin_family = hp -> h_addrtype) != isock -> sin_family) return tsaplose (td, DR_ADDRESS, NULLCP, "address family mismatch"); inaddr_copy (hp, lsock); } else lsock = NULL; if ((fd = start_tcp_client (lsock, 0)) == NOTOK) return tsaplose (td, DR_CONGEST, "socket", "unable to start"); #ifdef FIONBIO if (async) (void) ioctl (fd, FIONBIO, (onoff = 1, (char *) &onoff)); #endif tb -> tb_fd = fd; (void) TTService (tb); if (join_tcp_server (fd, isock) == NOTOK) { #ifdef NODELAY if (async) switch (errno) { case EINPROGRESS: if (peers == NULL) { peers = (struct sockaddr_in *) calloc ((unsigned) getdtablesize (), sizeof *peers); if (peers == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); (void) close_tcp_socket (fd); return (tb -> tb_fd = NOTOK); } FD_ZERO (&inprogress); } FD_SET (fd, &inprogress); peers[fd] = *isock;/* struct copy */ return OK; case EISCONN: goto done; default: break; } #endif (void) tsaplose (td, DR_REFUSED, "connection", "unable to establish"); (void) close_tcp_socket (fd); return (tb -> tb_fd = NOTOK); } #ifdef NODELAY done: ; #endif #ifdef FIONBIO if (async) (void) ioctl (fd, FIONBIO, (onoff = 0, (char *) &onoff)); #endif return DONE; } /* \f */ #ifndef NODELAY /* ARGSUSED */ #endif static int tcpretry (tb, td) struct tsapblk *tb; struct TSAPdisconnect *td; { #ifdef NODELAY #ifdef FIONBIO int onoff; #endif int fd = tb -> tb_fd; fd_set mask; struct sockaddr_in *isock = &peers[fd]; FD_ZERO (&mask); FD_SET (fd, &mask); if (xselect (fd + 1, NULLFD, &mask, NULLFD, 0) < 1) return OK; if (!FD_ISSET (fd, &inprogress)) return DONE; isock = &peers[fd]; if (join_tcp_server (fd, isock) == NOTOK) { switch (errno) { case EINPROGRESS: return OK; case EISCONN: goto done; case EINVAL: /* UNIX bug: could be any socket errno, e.g., ETIMEDOUT */ errno = ECONNREFUSED; /* and fall */ default: break; } (void) tsaplose (td, DR_REFUSED, "connection", "unable to establish"); FD_CLR (fd, &inprogress); (void) close_tcp_socket (fd); return (tb -> tb_fd = NOTOK); } done: ; #ifdef FIONBIO (void) ioctl (fd, FIONBIO, (onoff = 0, (char *) &onoff)); #endif FD_CLR (fd, &inprogress); return DONE; #else return tsaplose (td, DR_OPERATION, NULLCP, "connection not in progress"); #endif } /* \f init for read from network */ #ifndef BRIDGE_X25 static #endif int tcpinit (fd, t) int fd; register struct tsapkt *t; { register int cc, i; register char *bp; for (bp = (char *) &t -> t_pkthdr, i = TPKT_HDRLEN (t); i > 0; bp += cc, i -= cc) switch (cc = read_tcp_socket (fd, bp, i)) { case NOTOK: case OK: return DR_NETWORK; default: break; } if (t -> t_vrsn != TPKT_VRSN) return DR_PROTOCOL; if ((t -> t_length = ntohs (t -> t_length)) < TPKT_HDRLEN (t)) return DR_LENGTH; return OK; } /* \f write to network */ #ifndef BRIDGE_X25 static #endif int tcpwrite (fd, t, cp, n) int fd; register struct tsapkt *t; char *cp; int n; { register int cc; register struct udvec *uv; #ifdef WRITEV struct iovec iovs[NTPUV + 4]; register struct iovec *iov; #else register char *p, *q; #endif #ifdef WRITEV iov = iovs; cc = 0; iov -> iov_base = (char *) &t -> t_pkthdr; cc += (iov -> iov_len = TPKT_HDRLEN (t)); iov++; iov -> iov_base = cp; cc += (iov -> iov_len = n); iov++; if (t -> t_vdata) { iov -> iov_base = t -> t_vdata; cc += (iov -> iov_len = t -> t_vlen); iov++; } for (uv = t -> t_udvec; uv -> uv_base; uv++) { iov -> iov_base = uv -> uv_base; cc += (iov -> iov_len = uv -> uv_len); iov++; } if (writev (fd, iovs, iov - iovs) != cc) cc = NOTOK; #else cc = TPKT_HDRLEN (t) + n; if (t -> t_vdata) cc += t -> t_vlen; for (uv = t -> t_udvec; uv -> uv_base; uv++) cc += uv -> uv_len; if (p = malloc ((unsigned) cc)) { bcopy ((char *) &t -> t_pkthdr, q = p, TPKT_HDRLEN (t)); q += TPKT_HDRLEN (t); bcopy (cp, q, n); q += n; if (t -> t_vdata) { bcopy (t -> t_vdata, q, t -> t_vlen); q += t -> t_vlen; } for (uv = t -> t_udvec; uv -> uv_base; uv++) { bcopy (uv -> uv_base, q, uv -> uv_len); q += uv -> uv_len; } if (write_tcp_socket (fd, p, cc) != cc) cc = NOTOK; free (p); goto out; } SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("unable to malloc %d octets for pseudo-writev, continuing...", cc)); cc = TPKT_HDRLEN (t); if (write_tcp_socket (fd, (char *) &t -> t_pkthdr, cc) != cc) { err: ; cc = NOTOK; goto out; } if (write_tcp_socket (fd, cp, n) != n) goto err; cc += n; if (t -> t_vdata && write_tcp_socket (fd, t -> t_vdata, t -> t_vlen) != t -> t_vlen) goto err; cc += t -> t_vlen; for (uv = t -> t_udvec; uv -> uv_base; uv++) { if (write_tcp_socket (fd, uv -> uv_base, uv -> uv_len) != uv -> uv_len) goto err; cc += uv -> uv_len; } out: ; #endif return cc; } /* \f */ /* ARGSUSED */ char *tcpsave (fd, sin, cp1, cp2, td) int fd; struct sockaddr_in *sin; char *cp1, *cp2; struct TSAPdisconnect *td; { static char buffer[BUFSIZ]; (void) sprintf (buffer, "%c%d %s %s", NT_TCP, fd, cp1, cp2); return buffer; } /* \f */ int tcprestore (tb, buffer, td) register struct tsapblk *tb; char *buffer; struct TSAPdisconnect *td; { int fd; char domain[NSAP_DOMAINLEN + 1]; register struct NSAPaddr *na; register struct TSAPaddr *ta; ta = &tb -> tb_initiating; ta -> ta_naddr = 1; na = ta -> ta_addrs; na -> na_type = NA_TCP; if (sscanf (buffer, "%d %s %s", &fd, na -> na_domain, domain) != 3 || fd < 0) return tsaplose (td, DR_PARAMETER, NULLCP, "bad initialization vector \"%s\"", buffer); tb -> tb_fd = fd; (void) TTService (tb); ta = &tb -> tb_responding; ta -> ta_naddr = 1; na = ta -> ta_addrs; na -> na_type = NA_TCP; (void) strncpy (na -> na_domain, domain, sizeof na -> na_domain); return OK; } /* \f */ int TTService (tb) register struct tsapblk *tb; { struct tsapkt *t; tb -> tb_flags |= TB_TCP; tb -> tb_tsdusize = TPKT_MAXLEN - (tb -> tb_tpduslop = sizeof t -> t_pkthdr + DT_MAGIC); tb -> tb_retryfnx = tcpretry; tb -> tb_initfnx = tcpinit; tb -> tb_readfnx = read_tcp_socket; tb -> tb_writefnx = tcpwrite; tb -> tb_closefnx = close_tcp_socket; tb -> tb_selectfnx = select_tcp_socket; tp0init (tb); } #endif