DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T t

⟦88ed3b7cf⟧ TextFile

    Length: 14882 (0x3a22)
    Types: TextFile
    Names: »tsbridge.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/others/tsbridge/tsbridge.c« 

TextFile

/* tsbridge.c: transport bridge - jpo version ! */

#ifndef lint
static char *rcsid = "$Header: /f/osi/others/tsbridge/RCS/tsbridge.c,v 7.2 90/01/11 18:36:55 mrose Exp $";
#endif

/*
 * $Header: /f/osi/others/tsbridge/RCS/tsbridge.c,v 7.2 90/01/11 18:36:55 mrose Exp $
 *
 * Contributed by Julian Onions, Nottingham University in the UK
 *
 *
 * $Log:	tsbridge.c,v $
 * Revision 7.2  90/01/11  18:36:55  mrose
 * real-sync
 * 
 * Revision 7.1  89/11/27  05:43:28  mrose
 * sync
 * 
 * Revision 7.0  89/11/23  22:11:12  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.
 *
 */


#include <signal.h>
#include <stdio.h>
#include <varargs.h>
#include "manifest.h"
#ifdef BSD42
#include <sys/file.h>
#endif
#ifdef SYS5
#include <fcntl.h>
#endif
#include "tsap.h"
#include "logger.h"
#include "psap.h"
#include "tailor.h"

/* \f

 */

static int debug = 1;
static int nbits = FD_SETSIZE;

static LLog _pgm_log = {
	"tsbridge.log",	NULLCP,	NULLCP,
	LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL,
	-1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK
};

LLog	*pgm_log = &_pgm_log;

static char	*myname = "tsbridge";

typedef struct ContTbl {
	struct TSAPaddr	src;
	struct TSAPaddr dest;
	unsigned int flags;
#define CONN_STRICT	01
#define CONN_TRANS	02
} ContTbl;
ContTbl con_tbl[FD_SETSIZE];
int con_tbl_cnt = 0;

static struct TSAPaddr *maketa ();
static struct TSAPaddr *getnewta ();
static ContTbl *find_connection ();

static void read_file ();

static void adios (), advise ();

static void ts_adios (), ts_advise ();
static void ts_close (), ts_discon ();

/* \f

 */

/* ARGSUSED */

main (argc, argv, envp)
int	argc;
char	**argv,
        **envp;
{
	struct TSAPdisconnect   tds;
	register struct TSAPdisconnect  *td = &tds;
	struct TSAPaddr tas, *ta = &tas;
	int	vecp;
	char	*vec[4];

	arginit (argv);

	envinit ();

	for (vecp = 0; vecp < con_tbl_cnt; vecp++) {
	    advise (LLOG_TRACE, NULLCP, "Listening on %s",
		     taddr2str (&con_tbl[vecp].src));
	    if (TNetListen (&con_tbl[vecp].src, td) == NOTOK) {
		advise (LLOG_FATAL, NULLCP, "Listen failed on \"%s\"",
			taddr2str (&con_tbl[vecp].src));
		ts_adios (td, "listen failed");
	    }
	}

	for (;;) {
		if (TNetAcceptAux (&vecp, vec, NULLIP, ta, 0, NULLFD, NULLFD,
				   NULLFD, NOTOK, td) == NOTOK)
			ts_adios (td, "accept failed");

		if (vecp <= 0)
			continue;

		advise (LLOG_TRACE, NULLCP, "accepted new connection");
		switch (TNetFork (vecp, vec, td)) {
		    case OK:
			tsbridge (vecp, vec, ta);
			exit (1);
			/* NOTREACHED */

		    case NOTOK:
			ts_advise (td, LLOG_EXCEPTIONS, "fork failed");
			break;

		    default:
			break;
		}
	}
}

/* \f

 */

static	tsbridge (vecp, vec, ta)
int	vecp;
char	**vec;
struct TSAPaddr *ta;
{
	struct TSAPstart tss;
	register struct TSAPstart *ts = &tss;
	struct TSAPdisconnect   tds;
	register struct TSAPdisconnect  *td = &tds;
	struct TSAPaddr *tota;
	struct TSAPaddr *fromta;
	struct TSAPconnect tcs;
	struct TSAPconnect *tc = &tcs;
	int	sd;
	ContTbl *ctp;

	if (TInit (vecp, vec, ts, td) == NOTOK)
		ts_adios (td, "T-CONNECT.INDICATION failed");
		
	sd = ts -> ts_sd;
	advise (LLOG_NOTICE, NULLCP,
		"T-CONNECT.INDICATION: <%d, %s, %s, %d, %d>",
		ts -> ts_sd, taddr2str (&ts -> ts_calling),
		taddr2str (&ts -> ts_called),
		ts -> ts_expedited, ts -> ts_tsdusize);

	ctp = find_connection (ta);
	if (ctp == NULL) {
	    ts_close (sd, "Unknown listener address");
	    exit (1);
	}
	advise (LLOG_TRACE, NULLCP, "Accepted from address %s",
		taddr2str (&ctp -> src));

	tota = getnewta (&ts -> ts_called, sd, ctp);

	fromta = maketa (&ts -> ts_calling, tota -> ta_addrs[0].na_type, ctp);

	if ((ctp -> flags & CONN_TRANS) == 0) {
	    ts -> ts_expedited = 0;
	    if (ts -> ts_cc > 0) {
		advise (LLOG_EXCEPTIONS, NULLCP,
			"%d octets initial user-data",
			ts -> ts_cc);
		ts_close (sd, "initial user-data not allowed");
		exit (1);
	    }
	}
	
	advise (LLOG_NOTICE, NULLCP,
		"T-CONNECT.REQUEST: <%s, %s, %d, 0x%x/%d>",
		taddr2str (fromta), taddr2str (tota), ts -> ts_expedited,
		ts -> ts_data, ts -> ts_cc);

	if (TConnRequest (fromta, tota, ts -> ts_expedited,
			  ts -> ts_data, ts -> ts_cc, &ts -> ts_qos,
			  tc, td) == NOTOK) {
		ts_close (sd, "connection establishment failed");
		ts_adios(td, "T-CONNECT.REQUEST");
	}
	if (TConnResponse (sd, &tc -> tc_responding,
			   tc -> tc_expedited, tc -> tc_data, tc -> tc_cc,
			   &tc -> tc_qos, td) == NOTOK) {
		ts_close (sd, "connection establishment failed");
		ts_close (tc -> tc_sd, "connection establishment failed");
		ts_adios (td, "T-CONNECT.RESPONSE");
	}
	
	do_the_biz (sd, tc -> tc_sd);
}

/* \f

 */

static	do_the_biz (sd1, sd2)
int	sd1, sd2;
{
	int nfds = 0;
	fd_set rmask, imask;
	struct TSAPdisconnect   tds;
	register struct TSAPdisconnect  *td = &tds;

	FD_ZERO (&rmask);
	
	if (TSelectMask (sd1, &rmask, &nfds, td) == NOTOK
	        || TSelectMask (sd2, &rmask, &nfds, td) == NOTOK)
	    ts_adios (td, "TSelectMask failed");

	for (;;) {
		imask = rmask;
		if (xselect (nfds, &imask, NULLFD, NULLFD, NOTOK) == NOTOK)
			adios ("select", "failed");

		if (FD_ISSET (sd1, &imask))
			copy_tsdu (sd1, sd2);
		if (FD_ISSET (sd2, &imask))
			copy_tsdu (sd2, sd1);
	}
}

/* \f

 */

static	copy_tsdu (s1, s2)
int	s1, s2;
{
	struct TSAPdisconnect   tds;
	register struct TSAPdisconnect  *td = &tds;
	struct TSAPdata txs;
	register struct TSAPdata *tx = &txs;
	int	result;
	char	*p;

	if (TReadRequest (s1, tx, OK, td) == NOTOK) {
		if (td -> td_reason != DR_NORMAL)
			ts_adios (td, "TReadRequest");
		else	ts_discon (td, s2);
	}

	p = qb2str (&tx -> tx_qbuf);

	if (tx -> tx_expedited)
		result = TExpdRequest (s2, p, tx -> tx_cc, td);
	else
		result = TDataRequest (s2, p, tx -> tx_cc, td);

	free (p);
	TXFREE (tx);

	if (result == NOTOK) {
		if (td -> td_reason == DR_NORMAL)
			ts_discon (td, s1);

		ts_adios (td, tx -> tx_expedited ? "T-EXPEDITED-DATA.REQUEST"
						 : "T-DATA.REQUEST");
	}
}

/* \f

 */

static void ts_discon (td, sd)
struct TSAPdisconnect *td;
int	sd;
{
	ts_close (sd, "Normal Disconnect");
	ts_advise (td, LLOG_NOTICE, "T-DISCONNECT.INDICATION");

	exit (0);
}

/* \f

 */

static void ts_close (sd, event)
int	sd;
char	*event;
{
	struct TSAPdisconnect tds;
	register struct TSAPdisconnect *td = &tds;

	if (strlen (event) >= TD_SIZE)
	    event = NULLCP;
	if (TDiscRequest (sd, event, event ? strlen (event) + 1: 0, td)
	        == NOTOK)
	    ts_advise (td, LLOG_EXCEPTIONS, "T-DISCONNECT.REQUEST");
}

/* \f

 */

static void  ts_adios (td, event)
register struct TSAPdisconnect *td;
char	*event;
{
	ts_advise (td, LLOG_EXCEPTIONS, event);

	exit (1);
}

/* \f

 */

static void  ts_advise (td, code, event)
register struct TSAPdisconnect *td;
int     code;
char   *event;
{
    char    buffer[BUFSIZ];

    if (td -> td_cc > 0)
	(void) sprintf (buffer, "[%s] %*.*s",
		TErrString (td -> td_reason),
		td -> td_cc, td -> td_cc, td -> td_data);
    else
	(void) sprintf (buffer, "[%s]", TErrString (td -> td_reason));

    advise (code, NULLCP, "%s: %s", event, buffer);
}

/* \f

 */

static struct TSAPaddr *getnewta (ta, sd, ctp)
struct TSAPaddr *ta;
int	sd;
ContTbl *ctp;
{
	static struct TSAPaddr newta;
	struct TSAPaddr *nta = &newta;
	char	buffer[TSSIZE + 1];

	if (ctp -> flags & CONN_TRANS) {	/* make transparent address */
		*nta = ctp -> dest;	/* struct copy */
		nta -> ta_selectlen = ta -> ta_selectlen;
		bcopy (ta -> ta_selector, nta -> ta_selector,
		       ta -> ta_selectlen);
		return nta;
	}

	/* do the real TS bridge stuff */
	if (ta -> ta_selectlen == 0) {
		ts_close (sd, "no transport selector");
		adios (NULLCP, "no transport selector");
	}

	bcopy (ta -> ta_selector, buffer, ta -> ta_selectlen);
	buffer[ta -> ta_selectlen] = NULL;

	if ((nta = str2taddr (buffer)) == NULLTA) {
		ts_close (sd, "unable to translate address");
		adios (NULLCP, "unable to translate \"%s\"", buffer);
	}
	newta = *nta;

	return &newta;
}

/* \f

 */

static struct TSAPaddr *maketa (ta, type, ctp)
struct TSAPaddr *ta;
long	type;
ContTbl *ctp;
{
    static struct TSAPaddr newta;
    register struct TSAPaddr *nta = &newta;
    char	*p;
    int	i;
    struct PSAPaddr pas;
    struct PSAPaddr *pa = &pas;

    if (ctp -> flags & CONN_TRANS) {
	*nta = *ta;	/* struct copy */
    }
    else {
	bzero ((char *)pa, sizeof *pa);
	pa -> pa_addr.sa_addr = *ta;
	if ((p = _paddr2str (pa, NULLNA, -1)) == NULL) {
	    if (ctp -> flags & CONN_STRICT)
		adios (NULLCP, "unable to convert address to text");
	    advise (LLOG_NOTICE, NULLCP,
		    "unable to convert address to text");
	    return ta;		/* this may work... */
	}
	else {
	    if ((nta -> ta_selectlen = strlen (p)) >= TSSIZE) {
		if (ctp -> flags & CONN_STRICT)
		    adios (NULLCP, "new selector \"%s\" is too big",
			   p);

		advise (LLOG_NOTICE, NULLCP,
			"new selector \"%s\" is too big", p);
		return ta;
	    }
	    else
		bcopy (p, nta -> ta_selector, TSSIZE);
	}
    }
    for (i = 0; i < ctp -> src.ta_naddr; i++) {
	if (ctp -> src.ta_addrs[i].na_type == type) {
	    /* our address */
	    nta -> ta_addrs[0] = ctp->src.ta_addrs[i]; 
	    nta -> ta_naddr = 1;
	    return nta;
	}
    }
    if (ctp -> flags & CONN_STRICT)
	adios (NULLCP, "not listening on this network (%d)", type);

    advise (LLOG_NOTICE, NULLCP,
	    "not listening on this network (%d)", type);

    return ta;
}

/* \f

 */

static ContTbl *find_connection (ta)
struct TSAPaddr *ta;
{
    ContTbl *ctp;
    struct NSAPaddr *na1, *na2;

    for (ctp = con_tbl; ctp < &con_tbl[con_tbl_cnt]; ctp ++) {
	for (na1 = &ctp -> src.ta_addrs[0];
	     na1 < &ctp -> src.ta_addrs[ctp->src.ta_naddr]; na1++) {
	    for (na2 = &ta -> ta_addrs[0];
		 na2 < &ta -> ta_addrs[ta->ta_naddr]; na2 ++) {
		if (na1 -> na_type != na2 -> na_type)
		    continue;

		switch (na1 -> na_type) {
		case NA_NSAP:
		    if (na1 -> na_addrlen == na2 -> na_addrlen &&
			bcmp (na1 -> na_address, na2 -> na_address,
			      na1 -> na_addrlen) == 0)
			return ctp;
		    break;

		case NA_TCP:
		    if (na1 -> na_port == na2 -> na_port &&
		       strcmp (na1 -> na_domain, na2 -> na_domain) == 0)
			return ctp;
		    break;

		case NA_X25:
		case NA_BRG:
		    if (na1 -> na_dtelen == na2 -> na_dtelen &&
			bcmp (na1 -> na_dte, na2 -> na_dte,
			      na1 -> na_dtelen) == 0 &&
			na1 -> na_pidlen == na2 -> na_pidlen &&
			bcmp (na1 -> na_pid, na2 -> na_pid,
			      na1 -> na_pidlen) == 0)
			return ctp;
		    break;
		}
	    }
	}
    }
    return NULL;
}

/* \f

 */

static	arginit (vec)
char	**vec;
{
	register char   *ap;
	register struct TSAPaddr *ta;

	if (myname = rindex (*vec, '/'))
		myname++;
	if (myname == NULL || *myname == NULL)
		myname = *vec;

	for (vec++; ap = *vec; vec++) {
	    if (*ap == '-' && ap[1])
		switch (*++ap) {
		    case 'T':
		    	if ((ap = *++vec) == NULL || *ap == '-')
			    adios (NULLCP, "usage: %s -T tailorfile", myname);
		    	(void) isodesetailor (ap);
			isodetailor (myname, 0);
			ll_hdinit (pgm_log, myname);
			continue;

		    case 'a':
		        if ((ap = *++vec) == NULL || *ap == '-')
			    adios (NULLCP, "usage: %s -a address", myname);
			if ((ta = str2taddr (ap)) == NULLTA)
			    adios (NULLCP, "bad address \"%s\"", ap);
			con_tbl[0].src = *ta; /* struct copy */
			con_tbl[0].flags =  0;
			con_tbl_cnt = 1;
		        continue;

		    case 's':
			con_tbl[0].flags |= CONN_STRICT;
			continue;

		    default:
			adios (NULLCP, "unknown switch -%s", ap);
		}
	    else
		break;
	    
	}
	isodetailor (myname, 0);
	ll_hdinit (pgm_log, myname);

	for (; ap = *vec; vec++)
	    read_file (ap);

	if (con_tbl_cnt <= 0) {
	    if ((ta = str2taddr (tsb_default_address)) == NULLTA)
		adios (NULLCP, "bad default address \"%s\"",
		       tsb_default_address);
	    con_tbl[0].src = *ta; /* struct copy */
	    con_tbl_cnt = 1;
	}
}

/* \f

 */

static void read_file (file)
char	*file;
{
    FILE	*fp;
    char	buf[BUFSIZ];
    char	*vec[50];
    char	*ap;
    int		vecp, i;
    ContTbl	*ctp;
    struct TSAPaddr *ta;

    if (strcmp (file, "-") == 0)
	fp = stdin;
    else if ((fp = fopen (file, "r")) == NULL)
	adios (file, "Can't open ");

    while (fgets (buf, sizeof buf, fp) != NULLCP) {
	if (buf[0] == '#' || buf[0] == '\n')
	    continue;

	vecp = sstr2arg (buf, 50, vec, " \t,\n");
	if (vecp <= 0)
	    continue;

	if ((ta = str2taddr (vec[0])) == NULLTA)
	    adios (NULLCP, "Bad address \"%s\" in file %s", vec[0], file);

	ctp = &con_tbl[con_tbl_cnt];
	ctp -> src = *ta; /* struct copy */
	con_tbl_cnt ++;

	for (i = 1; i < vecp; i++) {
	    ap = vec[i];
	    if (*ap == '\0')
		continue;
	    if (*ap == '-') {
		switch (*++ap) {
		case 's':
		    ctp -> flags |= CONN_STRICT;
		    break;
		case 't':
		    ctp -> flags |= CONN_TRANS;
		    break;

		default:
		    adios (NULLCP, "Unknown option -%c", *ap);
		}
	    }
	    else {
		if ((ta = str2taddr (ap)) == NULLTA)
		    adios (NULLCP, "Bad address \"%s\" in file %s",
			   ap, file);
		ctp -> dest = *ta; /* struct copy */
		ctp -> flags |= CONN_TRANS;
	    }
	}	    
	
    }

    if (strcmp (file, "-") != 0)
	(void) fclose (fp);
}

/* \f

 */

static	envinit () {
	int     i,
		sd;

	nbits = getdtablesize ();

	if (!(debug = isatty (2))) {
		for (i = 0; i < 5; i++) {
			switch (fork ()) {
			    case NOTOK: 
				sleep (5);
				continue;

			    case OK: 
				break;

			    default: 
				_exit (0);
			}
			break;
		}

		(void) chdir ("/");

		if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
			adios ("/dev/null", "unable to read");
		if (sd != 0)
			(void) dup2 (sd, 0), (void) close (sd);
		(void) dup2 (0, 1);
		(void) dup2 (0, 2);

#ifdef  TIOCNOTTY
		if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
			(void) ioctl (sd, TIOCNOTTY, NULLCP);
			(void) close (sd);
		}
#else
#ifdef  SYS5
		(void) setpgrp ();
		(void) signal (SIGINT, SIG_IGN);
		(void) signal (SIGQUIT, SIG_IGN);
#endif
#endif
	}
	else
		ll_dbinit (pgm_log, myname);

#ifndef sun			/* damn YP... */
	for (sd = 3; sd < nbits; sd++)
	    if (pgm_log -> ll_fd != sd)
		(void) close (sd);
#endif

	(void) signal (SIGPIPE, SIG_IGN);

	ll_hdinit (pgm_log, myname);
	advise (LLOG_NOTICE, NULLCP, "starting");
}

/* \f

   ERRORS */

#ifndef lint
static void    adios (va_alist)
va_dcl
{
    va_list ap;

    va_start (ap);

    _ll_log (pgm_log, LLOG_FATAL, ap);

    va_end (ap);

    _exit (1);
}
#else
/* VARARGS */

static void    adios (what, fmt)
char   *what,
       *fmt;
{
    adios (what, fmt);
}
#endif


#ifndef lint
static void    advise (va_alist)
va_dcl
{
    int     code;
    va_list ap;

    va_start (ap);

    code = va_arg (ap, int);

    _ll_log (pgm_log, code, ap);

    va_end (ap);
}
#else
/* VARARGS */

static void    advise (code, what, fmt)
char   *what,
       *fmt;
int     code;
{
    advise (code, what, fmt);
}
#endif