|
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: 14882 (0x3a22) Types: TextFile Names: »tsbridge.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/others/tsbridge/tsbridge.c«
/* 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