|
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: 17472 (0x4440) Types: TextFile Names: »tsapd.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/support/tsapd.c«
/* tsapd.c - OSI transport server */ #ifndef lint static char *rcsid = "$Header: /f/osi/support/RCS/tsapd.c,v 6.0 89/03/18 23:45:02 mrose Rel $"; #endif /* * $Header: /f/osi/support/RCS/tsapd.c,v 6.0 89/03/18 23:45:02 mrose Rel $ * * * $Log: tsapd.c,v $ * Revision 6.0 89/03/18 23:45:02 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. * */ #include <errno.h> #include <signal.h> #include <stdio.h> #include <varargs.h> #include "manifest.h" #include <sys/ioctl.h> #include <sys/stat.h> #ifdef BSD42 #include <sys/file.h> #endif #ifdef SYS5 #include <fcntl.h> #endif #ifndef X_OK #define X_OK 1 #endif #ifndef NOGOSIP #include "rosap.h" #include "rtsap.h" #include "psap2.h" #include "ssap.h" #endif #include "tpkt.h" #ifdef TCP #include "internet.h" #endif #ifdef X25 #include "x25.h" #endif #ifdef CONS #include "cons.h" #endif #ifdef TP4 #include "tp4.h" #endif #include "isoservent.h" #include "logger.h" #include "tailor.h" /* \f */ static int debug = 1; static int nbits = FD_SETSIZE; static LLog _pgm_log = { "tsapd.log", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK }; LLog *pgm_log = &_pgm_log; static char *myname = "tsapd"; static char myhost[BUFSIZ]; static int tcpservice = 1; static int x25service = 1; static int consservice = 1; static int bridgeservice = 1; static int tp4service = 1; #define NTADDRS FD_SETSIZE static struct TSAPaddr *tz; static struct TSAPaddr tas[NTADDRS]; void adios (), advise (); void ts_advise (); #ifdef NOGOSIP #define ssapd NULLIFP #else int ssapd (), psapd (); #endif extern int errno; /* \f */ /* ARGSUSED */ main (argc, argv, envp) int argc; char **argv, **envp; { int failed, listening, vecp; char *vec[4]; register struct NSAPaddr *na; register struct TSAPaddr *ta; struct TSAPdisconnect tds; register struct TSAPdisconnect *td = &tds; arginit (argv); envinit (); failed = listening = 0; for (ta = tas; ta < tz; ta++) { if (ta -> ta_naddr == 0) { if (!tp4service) continue; advise (LLOG_NOTICE, NULLCP, "listening on TSEL %s", sel2str (ta -> ta_selector, ta -> ta_selectlen, 1)); } else { na = ta -> ta_addrs; switch (na -> na_type) { case NA_TCP: if (!tcpservice) continue; advise (LLOG_NOTICE, NULLCP, "listening on TCP %s %d", na -> na_domain, ntohs (na -> na_port)); break; case NA_X25: if (!x25service) continue; advise (LLOG_NOTICE, NULLCP, "listening on X.25 %s %s", na -> na_dte, sel2str (na -> na_pid, na -> na_pidlen, 1)); break; case NA_BRG: if (!bridgeservice) continue; advise (LLOG_NOTICE, NULLCP, "listening on X.25 (BRIDGE) %s %s", na -> na_dte, sel2str (na -> na_pid, na -> na_pidlen, 1)); break; case NA_NSAP: if (!tp4service && !consservice) continue; advise (LLOG_NOTICE, NULLCP, "listening on NS %s", sel2str (na -> na_address, na -> na_addrlen, 0)); break; default: adios (NULLCP, "unknown network type 0x%x", na -> na_type); /* NOTREACHED */ } if (ta -> ta_selectlen) advise (LLOG_NOTICE, NULLCP, " %s", sel2str (ta -> ta_selector, ta -> ta_selectlen, 1)); } if (TNetListen (ta, td) == NOTOK) { ts_advise (td, LLOG_EXCEPTIONS, "listen failed"); failed++; } else listening++; } if (!listening) adios (NULLCP, failed ? "no successful listens" : "no network services selected"); for (;;) { if (TNetAccept (&vecp, vec, 0, NULLFD, NULLFD, NULLFD, NOTOK, td) == NOTOK) { ts_advise (td, LLOG_EXCEPTIONS, "accept failed"); continue; } if (vecp <= 0) continue; switch (TNetFork (vecp, vec, td)) { case OK: tsapd (vecp, vec); exit (1); /* NOTREACHED */ case NOTOK: ts_advise (td, LLOG_EXCEPTIONS, "fork failed"); default: break; } } } /* \f */ static char buffer1[4096]; static char buffer2[32768]; static int tsapd (vecp, vec) int vecp; char **vec; { char buffer[BUFSIZ]; register struct isoservent *is; struct tsapblk *tb; struct TSAPstart tss; register struct TSAPstart *ts = &tss; struct TSAPdisconnect tds; register struct TSAPdisconnect *td = &tds; IFP hook; /* begin UGLY */ (void) strcpy (buffer1, vec[1]); (void) strcpy (buffer2, vec[2]); /* end UGLY */ if (TInit (vecp, vec, ts, td) == NOTOK) { ts_advise (td, LLOG_EXCEPTIONS, "T-CONNECT.INDICATION"); return; } /* used to print this in ssapd()... */ 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); hook = ssapd; if (ts -> ts_called.ta_selectlen) { if ((is = getisoserventbyselector ("tsap", ts -> ts_called.ta_selector, ts -> ts_called.ta_selectlen)) == NULL) { (void) sprintf (buffer, "OSI service tsap/%s not found", sel2str (ts -> ts_called.ta_selector, ts -> ts_called.ta_selectlen, 1)); goto out; } } else if (hook == NULLIFP || (is = getisoserventbyname ("session", "tsap")) == NULL) { (void) strcpy (buffer, "default session service not found"); goto out; } *is -> is_tail++ = buffer1; *is -> is_tail++ = buffer2; *is -> is_tail = NULL; if (tb = findtblk (ts -> ts_sd)) tb -> tb_fd = NOTOK; switch (hook ? (*hook) (is, td) : OK) { case NOTOK: ts_advise (td, LLOG_EXCEPTIONS, "service not started at tsap"); case DONE: exit (1); /* NOTREACHED */ case OK: default: (void) setperms (is); (void) execv (*is -> is_vec, is -> is_vec); (void) sprintf (buffer, "unable to exec %s: %s", *is -> is_vec, sys_errname (errno)); SLOG (pgm_log, LLOG_FATAL, NULLCP, ("%s", buffer)); break; } out: ; advise (LLOG_EXCEPTIONS, NULLCP, "%s", buffer); if (strlen (buffer) >= TD_SIZE) buffer[0] = NULL; (void) TDiscRequest (ts -> ts_sd, buffer, strlen (buffer) + 1, td); exit (1); } /* \f */ static int setperms (is) register struct isoservent *is; { struct stat st; if (stat (*is -> is_vec, &st) == NOTOK) { (void) setgid (1); (void) setuid (1); } else { (void) setgid (st.st_gid); (void) setuid (st.st_uid); } } /* \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 */ #ifndef NOGOSIP static int ssapd (is, td) register struct isoservent *is; register struct TSAPdisconnect *td; { int sd; struct TSAPstart tss; register struct TSAPstart *ts = &tss; struct SSAPindication sis; register struct SSAPabort *sa = &sis.si_abort; if (strcmp (is -> is_entity, "session") || strcmp (is -> is_provider, "tsap")) return OK; if (TInit (is -> is_tail - is -> is_vec, is -> is_vec, ts, td) == NOTOK) return NOTOK; sd = ts -> ts_sd; if (TConnResponse (sd, &ts -> ts_called, ts -> ts_expedited, NULLCP, 0, NULLQOS, td) == NOTOK) return NOTOK; if (SExec (ts, &sis, psapd, setperms) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "service not started at ssap: %s", SErrString (sa -> sa_reason)); if (sa -> sa_cc > 0) advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s", sa -> sa_cc, sa -> sa_cc, sa -> sa_data); SAFREE (sa); } return DONE; } /* \f */ #define RMASK \ "\020\01HALFDUPLEX\02DUPLEX\03EXPEDITED\04MINORSYNC\05MAJORSYNC\06RESYNC\ \07ACTIVITY\010NEGOTIATED\011CAPABILITY\012EXCEPTIONS\013TYPEDATA" static int psapd (is, si) register struct isoservent *is; register struct SSAPindication *si; { struct SSAPstart sss; register struct SSAPstart *ss = &sss; struct PSAPindication pis; register struct PSAPabort *pa = &pis.pi_abort; struct RtSAPindication rtis; register struct RtSAPabort *rta = &rtis.rti_abort; struct RoSAPindication rois; register struct RoSAPpreject *rop = &rois.roi_preject; if (strcmp (is -> is_provider, "ssap")) return OK; if (strcmp (is -> is_entity, "presentation") && strcmp (is -> is_entity, "rts") && strcmp (is -> is_entity, "ros")) return OK; /* begin UGLY */ (void) strcpy (buffer1, *(is -> is_tail - 2)); (void) strcpy (buffer2, *(is -> is_tail - 1)); /* end UGLY */ if (SInit (is -> is_tail - is -> is_vec, is -> is_vec, ss, si) == NOTOK) return NOTOK; advise (LLOG_NOTICE, NULLCP, "S-CONNECT.INDICATION: <%d, %s, %s, %s, %s, %ld, %d>", ss -> ss_sd, sprintref (&ss -> ss_connect), saddr2str (&ss -> ss_calling), saddr2str (&ss -> ss_called), sprintb (ss -> ss_requirements, RMASK), ss -> ss_isn, ss -> ss_ssdusize); if (strcmp (is -> is_entity, "presentation") == 0) { if (PExec (ss, &pis, buffer1, buffer2, NULLIFP, setperms) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "service not started at psap: %s", PErrString (pa -> pa_reason)); if (pa -> pa_cc > 0) advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s", pa -> pa_cc, pa -> pa_cc, pa -> pa_data); } return DONE; } if (strcmp (is -> is_entity, "rts") == 0) { if (RtExec (ss, &rtis, buffer1, buffer2, NULLIFP, setperms) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "service not started at rtsap: %s", RtErrString (rta -> rta_reason)); if (rta -> rta_cc > 0) advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s", rta -> rta_cc, rta -> rta_cc, rta -> rta_data); } } else { if (RoExec (ss, &rois, buffer1, buffer2, NULLIFP, setperms) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "service not started at rosap: %s", RoErrString (rop -> rop_reason)); if (rop -> rop_cc > 0) advise (LLOG_EXCEPTIONS, NULLCP, " %*.*s", rop -> rop_cc, rop -> rop_cc, rop -> rop_data); } } return DONE; } #endif /* \f */ static arginit (vec) char **vec; { int rflag; register char *ap; #ifdef TCP int port; struct NSAPaddr *tcp_na; struct servent *sp; #endif #ifdef X25 struct NSAPaddr *x25_na; #endif #ifdef CONS struct NSAPaddr *cons_na; #endif #ifdef BRIDGE_X25 struct NSAPaddr *bridge_na; #endif #ifdef TP4 register struct isoservent *is; #endif struct stat st; if (myname = rindex (*vec, '/')) myname++; if (myname == NULL || *myname == NULL) myname = *vec; isodetailor (myname, 0); ll_hdinit (pgm_log, myname); rflag = 0; (void) strcpy (myhost, TLocalHostName ()); bzero ((char *) tas, sizeof tas); tz = tas; #ifdef TCP if (!(ts_stacks & TS_TCP)) tcpservice = 0; if ((sp = getservbyname ("tsap", "tcp")) == NULL) adios (NULLCP, "tcp/tsap: unknown service"); tcp_na = tz -> ta_addrs; tcp_na -> na_type = NA_TCP; tcp_na -> na_domain[0] = NULL; tcp_na -> na_port = sp -> s_port; tz -> ta_naddr = 1; tz++; #endif #ifdef X25 if (!(ts_stacks & TS_X25)) x25service = 0; x25_na = tz -> ta_addrs; x25_na -> na_type = NA_X25; if (x25_local_dte && *x25_local_dte) { (void) strcpy (x25_na -> na_dte, x25_local_dte); x25_na -> na_dtelen = strlen (x25_na -> na_dte); } tz -> ta_naddr = 1; tz++; #endif #ifdef CONS if (!(ts_stacks & TS_CONS)) consservice = 0; cons_na = tz -> ta_addrs; cons_na -> na_type = NA_NSAP; (void) strcpy(cons_na -> na_address, cons_local_address); cons_na -> na_addrlen = strlen(cons_local_address); tz -> ta_naddr = 1; tz++; #endif #ifdef BRIDGE_X25 if (!(ts_stacks & TS_BRG)) bridgeservice = 0; bridge_na = tz -> ta_addrs; bridge_na -> na_type = NA_BRG; if (x25_bridge_listen && *x25_bridge_listen) { (void) strcpy (bridge_na -> na_dte, x25_bridge_listen); bridge_na -> na_dtelen = strlen (bridge_na -> na_dte); } if (x25_bridge_pid && *x25_bridge_pid) bridge_na -> na_pidlen = str2sel (x25_bridge_pid, -1, bridge_na -> na_pid, NPSIZE); tz -> ta_naddr = 1; tz++; #endif #ifdef TP4 if (!(ts_stacks & TS_TP4)) tp4service = 0; (void) setisoservent (0); while (is = getisoservent ()) if (strcmp (is -> is_provider, "tsap") == 0 && (strcmp (*is -> is_vec, "tsapd-bootstrap") == 0 || access (*is -> is_vec, X_OK) != NOTOK)) { if (strcmp (is -> is_entity, "isore") == 0) continue; if (tz >= tas + NTADDRS) { advise (LLOG_EXCEPTIONS, NULLCP, "too many services, starting with %s", is -> is_entity); break; } bcopy (is -> is_selector, tz -> ta_selector, tz -> ta_selectlen = is -> is_selectlen); tz -> ta_naddr = 0; tz++; } (void) endisoservent (); #endif for (vec++; ap = *vec; vec++) { if (*ap == '-') switch (*++ap) { case 't': ts_stacks = TS_TCP; tcpservice = 1; x25service = consservice = bridgeservice = tp4service = 0; continue; case 'x': ts_stacks = TS_X25; x25service = 1; tcpservice = consservice = bridgeservice = tp4service = 0; continue; case 'n': ts_stacks = TS_CONS; consservice = 1; tcpservice = x25service = bridgeservice = tp4service = 0; continue; case 'z': ts_stacks = TS_TP4; tp4service = 1; tcpservice = x25service = consservice = bridgeservice = 0; continue; case 'b': ts_stacks = TS_BRG; bridgeservice = 1; tcpservice = x25service = consservice = tp4service = 0; continue; case 'r': rflag = 1; continue; #ifdef TCP case 'p': if ((ap = *++vec) == NULL || *ap == '-' || (port = atoi (ap)) <= 0) adios (NULLCP, "usage: %s -p portno", myname); tcp_na -> na_port = htons ((u_short) port); continue; #endif #ifdef X25 /* This permits listening on a specific subaddress. */ case 'a': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage: %s -a x121address", myname); (void) strcpy (x25_na -> na_dte, ap); x25_na -> na_dtelen = strlen (ap); continue; /* This permits listening on a specific protocol id. In fact, SunLink X.25 lets you listen on a protocol id mask, but let's keep it simple. */ case 'i': if ((ap = *++vec) == NULL || *ap == '-' ) adios (NULLCP, "usage: %s -i pid", myname); x25_na -> na_pidlen = str2sel (ap, -1, x25_na -> na_pid, NPSIZE); continue; #endif #ifdef BRIDGE_X25 case 'A': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage %s -A x121address", myname); (void) strcpy (bridge_na -> na_dte, ap); bridge_na -> na_dtelen = strlen (ap); continue; case 'I': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage: %s -I pid", myname); bridge_na -> na_pidlen = str2sel (ap, -1, bridge_na -> na_pid, NPSIZE); continue; #endif default: adios (NULLCP, "-%s: unknown switch", ap); } adios (NULLCP, "usage: %s [switches]", myname); } if (!rflag && getuid () == 0 && stat (ap = isodefile ("isoservices"), &st) != NOTOK && st.st_uid != 0) adios (NULLCP, "%s not owned by root", ap); } /* \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++) (void) close (sd); #endif (void) signal (SIGPIPE, SIG_IGN); ll_hdinit (pgm_log, myname); advise (LLOG_NOTICE, NULLCP, "starting"); } /* \f */ /* \f ERRORS */ #ifndef lint 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 */ void adios (what, fmt) char *what, *fmt; { adios (what, fmt); } #endif #ifndef lint 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 */ void advise (code, what, fmt) char *what, *fmt; int code; { advise (code, what, fmt); } #endif