/* tsapd.c - OSI transport listener */ #ifndef lint static char *rcsid = "$Header: /f/osi/support/RCS/tsapd.c,v 7.12 91/02/22 09:46:59 mrose Interim $"; #endif /* * $Header: /f/osi/support/RCS/tsapd.c,v 7.12 91/02/22 09:46:59 mrose Interim $ * * * $Log: tsapd.c,v $ * Revision 7.12 91/02/22 09:46:59 mrose * Interim 6.8 * * Revision 7.11 90/12/19 09:16:14 mrose * touch-up * * Revision 7.10 90/12/17 22:13:27 mrose * -call * * Revision 7.9 90/12/11 10:52:29 mrose * lock-and-load * * Revision 7.8 90/11/05 14:10:32 mrose * oops * * Revision 7.7 90/10/30 14:25:32 mrose * update * * Revision 7.6 90/10/29 18:37:25 mrose * updates * * Revision 7.5 90/10/16 11:21:04 mrose * update * * Revision 7.4 90/10/15 22:54:26 mrose * typo * * Revision 7.3 90/10/15 18:18:47 mrose * iaed * * Revision 7.2 90/07/09 14:51:00 mrose * sync * * Revision 7.1 90/02/19 13:09:53 mrose * update * * Revision 7.0 89/11/23 22:27:46 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 <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 #ifdef IAE #include <quipu/util.h> #include <quipu/bind.h> #include <quipu/list.h> #include <quipu/ds_search.h> #define NOGOSIP #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 TP4 #include "tp4.h" #endif #ifndef IAE #include "isoservent.h" #endif #include "tailor.h" /* */ static int debug = 0; static int nbits = FD_SETSIZE; static LLog _pgm_log = { #ifndef IAE "tsapd.log", #else "iaed.log", #endif NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK }; LLog *pgm_log = &_pgm_log; static char *pgmname = "tsapd"; static char myhost[BUFSIZ]; static int tcpservice = 1; static int x25service = 1; static int bridgeservice = 1; static int tp4service = 1; static int *services[] = { &tp4service, &tcpservice, &x25service, &bridgeservice }; #define NTADDRS FD_SETSIZE static int listening = 0; static struct TSAPaddr *tz; static struct TSAPaddr tas[NTADDRS]; #ifdef IAE #define IAETIME (24 * 60 * 60L) static int isbound = 0; static int main_dsa = NOTOK; static int referral_dsa = NOTOK; static long nextime; static DN userdn = NULL; static char passwd[DBA_MAX_PASSWD_LEN]; static AttributeType t_ev; static AttributeType t_pa; static struct ds_search_arg search_arg; struct IAEntry { struct TSAPaddr is_addr; char *is_vector; char **is_vec; char **is_tail; }; #define NENTRIES 100 static struct IAEntry *iz; static struct IAEntry iae[NENTRIES]; int str2dnY (); extern int dsa_ad; extern int dsa_dead; extern char *local_dit; extern struct PSAPaddr dsa_bound; extern int as_print (), dn_print (), de_print (), fi_print (); #endif void adios (), advise (); void ts_advise (); #ifdef NOGOSIP #define ssapd NULLIFP #else int ssapd (), psapd (); #endif extern int errno; #ifdef IAE long time (); #endif /* */ /* ARGSUSED */ main (argc, argv, envp) int argc; char **argv, **envp; { int failed, vecp; char *vec[4]; register struct TSAPaddr *ta; struct TSAPdisconnect tds; register struct TSAPdisconnect *td = &tds; arginit (argv); envinit (); failed = 0; for (ta = tas; ta < tz; ta++) { register struct NSAPaddr *na; if (ta -> ta_naddr) { if (((na = ta -> ta_addrs) -> na_stack < 0 || na -> na_stack >= sizeof services / sizeof services[0])) adios (NULLCP, "unknown network type 0x%x", na -> na_stack); } else na = NULLNA; if (!*services[na ? na -> na_stack : NA_NSAP]) continue; advise (LLOG_NOTICE, NULLCP, "listening on %s", taddr2str (ta)); if (TNetListen (ta, td) == NOTOK) { ts_advise (td, LLOG_EXCEPTIONS, "TNetListen failed"); failed++; } else listening++; } if (!listening) adios (NULLCP, failed ? "no successful listens" : "no network services selected"); for (;;) { #ifdef IAE int secs; long now; (void) time (&now); now++; if ((secs = (int) (nextime - now)) <= 0) { search_directory (0); secs = IAETIME; } #else #define secs NOTOK #endif if (TNetAccept (&vecp, vec, 0, NULLFD, NULLFD, NULLFD, secs, td) == NOTOK) { ts_advise (td, LLOG_EXCEPTIONS, "TNetAccept failed"); continue; } if (vecp <= 0) continue; if (debug) break; switch (TNetFork (vecp, vec, td)) { case OK: #ifdef IAE (void) signal (SIGHUP, SIG_DFL); #endif ll_hdinit (pgm_log, pgmname); break; case NOTOK: ts_advise (td, LLOG_EXCEPTIONS, "TNetFork failed"); default: continue; } break; } tsapd (vecp, vec); } /* */ static char buffer1[4096]; static char buffer2[32768]; static int tsapd (vecp, vec) int vecp; char **vec; { char buffer[BUFSIZ]; #ifndef IAE register struct isoservent *is; #else register struct IAEntry *is; #endif 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) { #ifndef IAE if ((is = getisoserventbyselector ("tsap", ts -> ts_called.ta_selector, ts -> ts_called.ta_selectlen)) == NULL) { #else for (is = iae; is < iz; is++) if (is -> is_addr.ta_selectlen == ts -> ts_called.ta_selectlen && bcmp (is -> is_addr.ta_selector, ts -> ts_called.ta_selector, is -> is_addr.ta_selectlen) == 0) break; if (is >= iz) { #endif (void) sprintf (buffer, "OSI service tsap/%s not found", sel2str (ts -> ts_called.ta_selector, ts -> ts_called.ta_selectlen, 1)); goto out; } } else #ifndef IAE if (hook == NULLIFP || (is = getisoserventbyname ("session", "tsap")) == NULL) #endif { (void) strcpy (buffer, "default session service not found"); goto out; } #ifndef IAE *is -> is_tail++ = buffer1; *is -> is_tail++ = buffer2; *is -> is_tail = NULL; #else is -> is_tail[0] = buffer1; is -> is_tail[1] = buffer2; is -> is_tail[2] = NULL; #endif 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); { register char **lp = is->is_vec; int arg = 0; while(*lp) { printf("arg %d is %s\n", arg, *lp); arg++; lp++; } } (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); } /* */ static int setperms (is) #ifndef IAE register struct isoservent *is; #else register struct IAEntry *is; #endif { 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); } } /* */ 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); } /* */ #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; } /* */ #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 /* */ #ifndef IAE static arginit (vec) char **vec; { int rflag; register char *ap; #ifdef TCP int port; struct NSAPaddr *tcp_na; register struct servent *sp; #endif #ifdef X25 struct NSAPaddr *x25_na; #endif #ifdef BRIDGE_X25 struct NSAPaddr *bridge_na; #endif #ifdef TP4 register struct isoservent *is; #endif struct stat st; if (pgmname = rindex (*vec, '/')) pgmname++; if (pgmname == NULL || *pgmname == NULL) pgmname = *vec; isodetailor (pgmname, 0); ll_hdinit (pgm_log, pgmname); 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 && (sp = getservbyname ("iso-tsap", "tcp")) == NULL) advise (LLOG_EXCEPTIONS, NULLCP, "tcp/tsap: unknown service"); tcp_na = tz -> ta_addrs; tcp_na -> na_stack = NA_TCP; tcp_na -> na_community = ts_comm_tcp_default; tcp_na -> na_domain[0] = NULL; tcp_na -> na_port = sp ? sp -> s_port : htons ((u_short) 102); tz -> ta_naddr = 1; tz++; #endif #ifdef X25 if (!(ts_stacks & TS_X25)) x25service = 0; x25_na = tz -> ta_addrs; x25_na -> na_stack = NA_X25; x25_na -> na_community = ts_comm_x25_default; 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); } if (x25_local_pid && *x25_local_pid) x25_na -> na_pidlen = str2sel (x25_local_pid, -1, x25_na -> na_pid, NPSIZE); tz -> ta_naddr = 1; tz++; #endif #ifdef BRIDGE_X25 if (!(ts_stacks & TS_BRG)) bridgeservice = 0; bridge_na = tz -> ta_addrs; bridge_na -> na_stack = NA_BRG; bridge_na -> na_community = ts_comm_x25_default; 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 'd': debug++; continue; case 't': ts_stacks = TS_TCP; tcpservice = 1; x25service = bridgeservice = tp4service = 0; continue; case 'x': ts_stacks = TS_X25; x25service = 1; tcpservice = bridgeservice = tp4service = 0; continue; case 'z': ts_stacks = TS_TP4; tp4service = 1; tcpservice = x25service = bridgeservice = 0; continue; case 'b': ts_stacks = TS_BRG; bridgeservice = 1; tcpservice = x25service = 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", pgmname); 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", pgmname); (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", pgmname); 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", pgmname); (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", pgmname); 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]", pgmname); } if (!rflag && getuid () == 0 && stat (ap = isodefile ("isoservices", 0), &st) != NOTOK && st.st_uid != 0) adios (NULLCP, "%s not owned by root", ap); } /* */ #else static arginit (vec) char **vec; { int argp, options; register char *ap; char base[BUFSIZ], **argptr, *args[4]; if (pgmname = rindex (*vec, '/')) pgmname++; if (pgmname == NULL || *pgmname == NULL) pgmname = *vec; isodetailor (pgmname, 0); ll_hdinit (pgm_log, pgmname); quipu_syntaxes (); argp = 0; args[argp++] = pgmname; for (argptr = vec, argptr++; ap = *argptr; argptr++) { if (*ap == '-') switch (*++ap) { case 'D': case 'u': case 'p': if ((ap = *++argptr) == NULL || *ap == '-') break; continue; case 'c': if ((ap = *++argptr) == NULL || *ap == '-') break; args[argp++] = "-c"; args[argp++] = ap; break; default: continue; } break; } args[argp] = NULLCP; dsap_init (&argp, (argptr = args, &argptr)); (void) strcpy (myhost, TLocalHostName ()); (void) strcpy (base, local_dit); if (!(ts_stacks & TS_TCP)) tcpservice = 0; if (!(ts_stacks & TS_X25)) x25service = 0; if (!(ts_stacks & TS_BRG)) bridgeservice = 0; if (!(ts_stacks & TS_TP4)) tp4service = 0; options = SVC_OPT_PREFERCHAIN; userdn = NULLDN, passwd[0] = NULL; for (vec++; ap = *vec; vec++) { if (*ap == '-') switch (*++ap) { case 'd': debug++; ll_dbinit (pgm_log, pgmname); continue; case 't': ts_stacks = TS_TCP; tcpservice = 1; x25service = bridgeservice = tp4service = 0; continue; case 'x': ts_stacks = TS_X25; x25service = 1; tcpservice = bridgeservice = tp4service = 0; continue; case 'z': ts_stacks = TS_TP4; tp4service = 1; tcpservice = x25service = bridgeservice = 0; continue; case 'b': ts_stacks = TS_BRG; bridgeservice = 1; tcpservice = x25service = tp4service = 0; continue; case 'r': /* ignored... */ continue; case 'D': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage: %s -D DIT", pgmname); if (*ap == '@') (void) strcpy (base, ap); else (void) sprintf (base, "%s@%s", local_dit, ap); continue; case 'm': options |= SVC_OPT_DONTUSECOPY; continue; case 'c': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage: %s -c DSA-name-or-address", pgmname); continue; case 'u': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage: %s -u username", pgmname); if ((userdn = str2dn (*ap != '@' ? ap : ap + 1)) == NULLDN) adios (NULLCP, "invalid DN for username: %s", ap); bzero ((char *) ap, strlen (ap)); continue; case 'p': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage: %s -p password", pgmname); (void) strcpy (passwd, ap); bzero ((char *) ap, strlen (ap)); continue; default: adios (NULLCP, "-%s: unknown switch", ap); } adios (NULLCP, "usage: %s [switches]", pgmname); } { Attr_Sequence as; AttributeType t_oc; DN local_dn; register Filter fi; register struct ds_search_arg *sa = &search_arg; if ((t_ev = str2AttrT ("execVector")) == NULL) adios (NULLCP, "unknown attribute type \"%s\"", "execVector"); if ((t_oc = str2AttrT ("objectClass")) == NULL) adios (NULLCP, "unknown attribute type \"%s\"", "objectClass"); if ((t_pa = str2AttrT ("presentationAddress")) == NULL) adios (NULLCP, "unknown attribute type \"%s\"", "presentationAddress"); if (str2dnY (*base != '@' ? base : base + 1, &local_dn) == NOTOK) adios (NULLCP, "DIT subtree invalid: \"%s\"", base); fi = filter_alloc (); bzero ((char *) fi, sizeof *fi); fi -> flt_type = FILTER_ITEM; fi -> FUITEM.fi_type = FILTERITEM_EQUALITY; fi -> FUITEM.UNAVA.ava_type = AttrT_cpy (t_oc); if ((fi -> FUITEM.UNAVA.ava_value = str2AttrV ("iSODEApplicationEntity", fi -> FUITEM.UNAVA.ava_type -> oa_syntax)) == NULL) adios (NULLCP, "unknown attribute value \"%s\" for \"%s\"", "iSODEApplicationEntity", "objectClass"); as = as_merge (as_comp_new (AttrT_cpy (t_ev), NULLAV, NULLACL_INFO), as_comp_new (AttrT_cpy (t_pa), NULLAV, NULLACL_INFO)); bzero ((char *) sa, sizeof *sa); sa -> sra_common.ca_servicecontrol.svc_options = options; sa -> sra_common.ca_servicecontrol.svc_timelimit = SVC_NOTIMELIMIT; sa -> sra_common.ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT; sa -> sra_baseobject = local_dn; sa -> sra_subset = SRA_WHOLESUBTREE; sa -> sra_filter = fi; sa -> sra_searchaliases = TRUE; sa -> sra_eis.eis_allattributes = FALSE; sa -> sra_eis.eis_select = as; sa -> sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; search_directory (1); } } /* */ static search_directory (firstime) int firstime; { int i; register struct ds_search_arg *sa = &search_arg; struct ds_search_result search_result; register struct ds_search_result *sr = &search_result; struct DSError error; register struct DSError *se = &error; register EntryInfo *ptr; register struct IAEntry *ia; register struct TSAPaddr *ta, *tb, *ty; struct TSAPaddr tys[NTADDRS]; advise (LLOG_NOTICE, NULLCP, "searching directory for iSODEApplicationEntity objects"); while (rebind_to_directory () == NOTOK) { if (!firstime) return; if (debug) advise (LLOG_DEBUG, NULLCP, "sleeping for 5 minutes..."); sleep ((unsigned) 5 * 60); } for (;;) { if (debug) { pslog (pgm_log, LLOG_DEBUG, "performing subtree search of", dn_print, (caddr_t) sa -> sra_baseobject); pslog (pgm_log, LLOG_DEBUG, " for", fi_print, (caddr_t) sa -> sra_filter); } if (ds_search (sa, se, sr) == DS_OK) break; if (do_error (se) == NOTOK) { if (!firstime) return; adios (NULLCP, "search failed"); } sa -> sra_baseobject = se -> ERR_REFERRAL.DSE_ref_candidates -> cr_name; } if (sr -> srr_correlated != TRUE) correlate_search_results (sr); if (!firstime) for (ia = iae; ia < iz; ia++) { free (ia -> is_vector); free (ia -> is_vec[0]); free ((char *) ia -> is_vec); } bzero ((char *) iae, sizeof iae); iz = iae; bzero ((char *) tys, sizeof tys); ty = tys; i = 0; for (ptr = sr -> CSR_entries; ptr; ptr = ptr -> ent_next) { Attr_Sequence eptr; AV_Sequence avs; if (iz >= iae + NENTRIES) { pslog (pgm_log, LLOG_EXCEPTIONS, "too many services, starting with", dn_print, (caddr_t) ptr -> ent_dn); break; } if (debug) { pslog (pgm_log, LLOG_DEBUG, "processing", dn_print, (caddr_t) ptr -> ent_dn); pslog (pgm_log, LLOG_DEBUG, " attributes", as_print, (caddr_t) ptr -> ent_attr); } for (eptr = ptr -> ent_attr; eptr; eptr = eptr -> attr_link) { if (AttrT_cmp (eptr -> attr_type, t_pa) == 0) { if (avs = eptr -> attr_value) { register struct PSAPaddr *pa = (struct PSAPaddr *) avs -> avseq_av.av_struct; if ((ta = &pa -> pa_addr.sa_addr) -> ta_selectlen == 0 || pa -> pa_selectlen > 0 || pa -> pa_addr.sa_selectlen > 0) continue; iz -> is_addr = *ta; /* struct copy */ } continue; } if (AttrT_cmp (eptr -> attr_type, t_ev) == 0) { if (avs = eptr -> attr_value) { int vecp; register char **vp; char *cp, *evec[NVEC + NSLACK + 1]; cp = (char *) avs -> avseq_av.av_struct; if ((iz -> is_vector = malloc ((unsigned) (strlen (cp) + 1))) == NULL) adios (NULLCP, "out of memory allocating iaeVector"); (void) strcpy (iz -> is_vector, cp); if ((vecp = str2vec (iz -> is_vector, evec)) < 1) goto losing_iae; if ((iz -> is_vec = (char **) calloc ((unsigned) (vecp + 3), sizeof *iz -> is_vec)) == NULL) adios (NULLCP, "out of memory allocating execVector"); iz -> is_tail = iz -> is_vec, vp = evec; while (*iz -> is_tail++ = *vp++) continue; iz -> is_tail--; if (access (cp = isodefile (iz -> is_vec[0], 1), X_OK) == NOTOK) { advise (LLOG_EXCEPTIONS, cp, "unable to find program"); iz -> is_vec[0] = NULL; goto losing_iae; } if ((iz -> is_vec[0] = malloc ((unsigned) (strlen (cp) + 1))) == NULL) adios (NULLCP, "out of memory allocating pgmVector"); (void) strcpy (iz -> is_vec[0], cp); } continue; } } if ((ta = &iz -> is_addr) -> ta_selectlen == 0 || iz -> is_vector == NULL) { pslog (pgm_log, LLOG_EXCEPTIONS, "invalid entry", dn_print, (caddr_t) ptr -> ent_dn); losing_iae: ; if (iz -> is_vector) free (iz -> is_vector); if (iz -> is_vec) { if (iz -> is_vec[0]) free (iz -> is_vec[0]); free ((char *) iz -> is_vec); } bzero ((char *) iz, sizeof *iz); continue; } if (ta -> ta_naddr == 0) *ty++ = *ta; /* struct copy */ else { register int n = ta -> ta_naddr; register struct NSAPaddr *na = ta -> ta_addrs; for (; n > 0; na++, n--) { for (tb = tys; tb < ty; tb++) if (tb -> ta_naddr != 0 && bcmp ((char *) na, (char *) tb -> ta_addrs, sizeof *na) == 0) break; if (tb >= ty) { if (na -> na_type == NA_NSAP) bcopy (ta -> ta_selector, ty -> ta_selector, ty -> ta_selectlen = ta -> ta_selectlen); else ty -> ta_selectlen = 0; ty -> ta_naddr = 1; ty -> ta_addrs[0] = *na; /* struct copy */ ty++; } } } for (ia = iae; ia < iz; ia++) { tb = &ia -> is_addr; if (ta -> ta_selectlen == tb -> ta_selectlen && bcmp (ta -> ta_selector, tb -> ta_selector, ta -> ta_selectlen) == 0) { char buffer[BUFSIZ]; (void) strcpy (buffer, taddr2str (tb)); advise (LLOG_EXCEPTIONS, NULLCP, "two services with the same transport selector: %s and %s", buffer, taddr2str (ta)); pslog (pgm_log, LLOG_EXCEPTIONS, "starting with", dn_print, (caddr_t) ptr -> ent_dn); adios (NULLCP, "you lose big"); } } iz++, i++; } if (sr -> CSR_cr) { advise (LLOG_EXCEPTIONS, NULLCP, "partial results only (not all DSAs could be reached)"); } else if (sr -> CSR_limitproblem != LSR_NOLIMITPROBLEM) { advise (LLOG_EXCEPTIONS, NULLCP, "%s limit exceeded", sr -> CSR_limitproblem == LSR_TIMELIMITEXCEEDED ? "time" : sr -> CSR_limitproblem == LSR_SIZELIMITEXCEEDED ? "size" : "administrative"); } if (i == 0) adios (NULLCP, "search failed to find anything"); else if (debug) advise (LLOG_DEBUG, NULLCP, "%d match%s found", i, i != 1 ? "es" : ""); dn_free (sr -> CSR_object); entryinfo_free (sr -> CSR_entries, 0); crefs_free (sr -> CSR_cr); (void) unbind_from_directory (); if (!firstime) { int failed = 0; struct TSAPdisconnect tds; for (ta = tas; ta < tz; ta++) { for (tb = tys; tb < ty; tb++) if (bcmp ((char *) ta, (char *) tb, sizeof *ta) == 0) break; if (tb >= ty) { advise (LLOG_NOTICE, NULLCP, "closing %s", taddr2str (ta)); if (TNetClose (ta, &tds) == NOTOK) ts_advise (&tds, LLOG_EXCEPTIONS, "TNetClose failed"); listening--; } } for (ta = tys; ta < ty; ta++) { for (tb = tas; tb < tz; tb++) if (bcmp ((char *) ta, (char *) tb, sizeof *ta) == 0) break; if (tb >= tz) { register struct NSAPaddr *na; if (ta -> ta_naddr) { if (((na = ta -> ta_addrs) -> na_stack < 0 || na -> na_stack >= sizeof services / sizeof services[0])) adios (NULLCP, "unknown network type 0x%x", na -> na_stack); } else na = NULLNA; if (!*services[na ? na -> na_stack : NA_NSAP]) continue; advise (LLOG_NOTICE, NULLCP, "listening on %s", taddr2str (ta)); if (TNetListen (ta, &tds) == NOTOK) { ts_advise (&tds, LLOG_EXCEPTIONS, "TNetListen failed"); failed++; } else listening++; } } if (!listening) adios (NULLCP, failed ? "no successful listens" : "no network services selected"); } bzero ((char *) tas, sizeof tas); tz = tas; for (ta = tys; ta < ty; *tz++ = *ta++) /* struct copy */ continue; if (debug) { advise (LLOG_DEBUG, NULLCP, "application entitites..."); for (ia = iae; ia < iz; ia++) advise (LLOG_DEBUG, NULLCP, " addr=%s vector=%s", taddr2str (&ia -> is_addr), ia -> is_vector); advise (LLOG_DEBUG, NULLCP, "transport addresses..."); for (ta = tas; ta < tz; ta++) advise (LLOG_DEBUG, NULLCP, " addr=%s", taddr2str (ta)); } (void) time (&nextime); nextime += IAETIME; } /* */ static bind_to_directory () { struct ds_bind_arg bind_arg, bind_result; register struct ds_bind_arg *ba = &bind_arg, *br = &bind_result; struct ds_bind_error bind_error; register struct ds_bind_error *be = &bind_error; static int very_first_time = 1; (void) unbind_from_directory (); make_bind_args (ba, br, be); if (debug) advise (LLOG_DEBUG, NULLCP, "connecting to DSA..."); if (secure_ds_bind (ba, be, br) != DS_OK) { if (very_first_time) very_first_time = 0; else advise (LLOG_EXCEPTIONS, NULLCP, "unable to connect: %s", be -> dbe_type == DBE_TYPE_SECURITY ? "security error" : "DSA unavailable"); isbound = 0; return; } very_first_time = 0; dn_free (br -> dba_dn); main_dsa = dsap_ad; advise (LLOG_NOTICE, NULLCP, "connected to %s", pa2str (&dsa_bound)); isbound = 1; } /* */ static int rebind_to_directory () { if (referral_dsa != NOTOK) { if (debug) advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa"); (void) dap_unbind (referral_dsa); referral_dsa = NOTOK; dsap_ad = main_dsa; } if (!isbound) (void) bind_to_directory (); return (isbound ? OK : NOTOK); } /* */ static int make_bind_args (ba, br, be) register struct ds_bind_arg *ba, *br; register struct ds_bind_error *be; { bzero ((char *) ba, sizeof *ba); bzero ((char *) br, sizeof *br); bzero ((char *) be, sizeof *be); ba -> dba_version = DBA_VERSION_V1988; if (ba -> dba_dn = userdn) ba -> dba_auth_type = DBA_AUTH_SIMPLE; if (ba -> dba_passwd_len = strlen (passwd)) (void) strcpy (ba -> dba_passwd, passwd); } /* */ static int unbind_from_directory () { int wasbound; if (wasbound = isbound) { if (referral_dsa != NOTOK) { if (debug) advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa"); (void) dap_unbind (referral_dsa); referral_dsa = NOTOK; dsap_ad = main_dsa; } (void) ds_unbind (); isbound = 0; } dsa_dead = 0; return wasbound; } /* */ static int do_error (de) register struct DSError *de; { if (de -> dse_type == DSE_REFERRAL && de -> ERR_REFERRAL.DSE_ref_candidates) { register struct access_point *ap; struct ds_bind_arg bind_arg, bind_result; register struct ds_bind_arg *ba = &bind_arg, *br = &bind_result; struct ds_bind_error bind_error; register struct ds_bind_error *be = &bind_error; ap = de -> ERR_REFERRAL.DSE_ref_candidates -> cr_accesspoints; if (referral_dsa != NOTOK) { if (debug) advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa"); (void) dap_unbind (referral_dsa); referral_dsa = NOTOK; dsap_ad = main_dsa; } make_bind_args (ba, br, be); pslog (pgm_log, LLOG_NOTICE, "referring to", dn_print, (caddr_t) ap -> ap_name); if (dap_bind (&referral_dsa, ba, be, br, ap -> ap_address) != DS_OK) { advise (LLOG_EXCEPTIONS, NULLCP, "unable to connect: %s", be -> dbe_type == DBE_TYPE_SECURITY ? "security error" : "DSA unavailable"); dsap_ad = main_dsa; ds_error_free (de); return NOTOK; } dsap_ad = referral_dsa; if (debug) advise (LLOG_DEBUG, NULLCP, "referral in progress"); ds_error_free (de); return OK; } pslog (pgm_log, LLOG_EXCEPTIONS, "DAP error:", de_print, (caddr_t) de); if (dsa_dead) { dsa_dead = 0; if (referral_dsa != NOTOK) { if (debug) advise (LLOG_DEBUG, NULLCP, "dap_unbind from referral dsa"); (void) dap_unbind (referral_dsa); referral_dsa = NOTOK; dsap_ad = main_dsa; } else (void) unbind_from_directory (); } return NOTOK; } /* */ int str2dnY (str, dn) char *str; DN *dn; { if (*str == NULL) { *dn = NULLDN; return OK; } return ((*dn = str2dn (str)) != NULLDN ? OK : NOTOK); } /* */ #ifdef BSD42 /* ARGSUSED */ #endif static SFD hupser (sig) int sig; { #ifndef BSD42 (void) signal (sig, hupser); #endif search_directory (0); } #endif /* */ static envinit () { int i, sd; nbits = getdtablesize (); if (debug == 0 && !(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 SETSID if (setsid () == NOTOK) advise (LLOG_EXCEPTIONS, "failed", "setsid"); #endif #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, pgmname); #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, pgmname); advise (LLOG_NOTICE, NULLCP, "starting"); #ifdef IAE (void) signal (SIGHUP, hupser); #endif } /* 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