|
|
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