|
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: 44325 (0xad25) Types: TextFile Names: »tsaplisten.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦e83f91978⟧ »EurOpenD22/isode/osimis-2.0.tar.Z« └─⟦d846658bd⟧ └─⟦this⟧ »osimis/misode/tsap/tsaplisten.c« └─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/tsap/tsaplisten.c«
/* tsaplisten.c - "network" listening */ #ifndef lint static char *rcsid = "$Header: /f/osi/tsap/RCS/tsaplisten.c,v 7.8 89/12/19 22:02:35 mrose Exp $"; #endif /* * $Header: /f/osi/tsap/RCS/tsaplisten.c,v 7.8 89/12/19 22:02:35 mrose Exp $ * * RFC1085 (LPP) support contributed by the Wollongong Group, Inc. * * * $Log: tsaplisten.c,v $ * Revision 7.8 89/12/19 22:02:35 mrose * touch-up * * Revision 7.7 89/12/19 16:21:35 mrose * sync * * Revision 7.6 89/12/13 07:05:50 mrose * touch-up * * Revision 7.5 89/12/11 09:35:37 mrose * again * * Revision 7.4 89/12/11 09:20:30 mrose * update * * Revision 7.3 89/12/07 22:15:45 mrose * touch-up * * Revision 7.2 89/12/07 01:07:43 mrose * queued writes * * Revision 7.1 89/11/25 16:31:39 mrose * sync * * Revision 7.0 89/11/23 22:30: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. * */ /* LINTLIBRARY */ #include <errno.h> #include <stdio.h> #include <signal.h> #include "tailor.h" #include "tpkt.h" #include "mpkt.h" #include <sys/ioctl.h> #ifdef BSD42 #include <sys/file.h> #endif #ifdef SYS5 #include <fcntl.h> #endif #ifdef LPP #undef X25 #undef BRIDGE_X25 #undef TP4 #endif #ifdef LPP #include "dgram.h" #endif #ifdef TCP #include "internet.h" #endif #ifdef X25 #include "x25.h" #endif #ifdef TP4 #include "tp4.h" #endif #ifdef LPP #undef MGMT #endif /* \f DATA */ union naddr { #ifdef TCP struct sockaddr_in lb_un_isock; #endif #if defined(X25) || defined(BRIDGE_X25) struct NSAPaddr lb_un_xsock; #endif #ifdef TP4 struct TSAPaddr lb_un_tsock; #endif int lb_dummy; }; struct listenblk { struct listenblk *lb_forw; /* doubly-linked list */ struct listenblk *lb_back; /* .. */ int lb_fd; /* network handle */ #define LISTEN_EXCEPTED (-2) /* magic value */ int lb_type; /* either listener, or exception handler */ #define LB_UNDEF 0 #define LB_LISTEN 1 #define LB_ACCEPT 2 #define LB_ACCEPTNOW 3 #define LB_EXCEPTION 4 #ifndef LPP #define LB_QUEUED 5 #endif IFP lb_magic; struct TSAPaddr lb_addr; /* transport address */ struct tsapblk *lb_tb; union naddr lb_un1; #define lb_loc_isock lb_un1.lb_un_isock #define lb_loc_xsock lb_un1.lb_un_xsock #define lb_loc_nsock lb_un1.lb_un_nsock #define lb_loc_tsock lb_un1.lb_un_tsock union naddr lb_un3; #define lb_rem_isock lb_un3.lb_un_isock #define lb_rem_xsock lb_un3.lb_un_xsock #define lb_rem_nsock lb_un3.lb_un_nsock #define lb_rem_tsock lb_un3.lb_un_tsock union { struct { IFP accept1; /* accept 1 function */ IFP accept2; /* accept 2 function */ } lb_un_accept; IFP lb_un_except; /* exception function */ } lb_un2; #define lb_accept1 lb_un2.lb_un_accept.accept1 #define lb_accept2 lb_un2.lb_un_accept.accept2 #define lb_except lb_un2.lb_un_except IFP lb_close; /* close function */ }; #define NULLLBP ((struct listenblk *) 0) static int once_only = 0; static struct listenblk listenque; static struct listenblk *LHead = &listenque; struct listenblk *findlblk (), *newlblk (), *findlblkbyfd (); /* * Event block abstraction. An event block is generated by interfaces * that might need to do things occasionally. Currently this is only * the bridge but other things should be slot inable. * The idea is you but a listenblk of the exception type on a fd. * If the fd `goes off' the listenblk is destroyed and an eventblk * created which will be called every 60 seconds for blocking listens, * and before each listen otherwise. */ struct eventblk { struct eventblk *ev_forw; /* doubly-linked list */ struct eventblk *ev_back; /* .. */ struct TSAPaddr ev_taddr; /* associated address */ IFP ev_eventfnx; /* the function to call */ }; #define NULLEVP ((struct eventblk *) 0) static struct eventblk eventqueue; static struct eventblk *EHead = &eventqueue; static int ev_onceonly = 0; static int ev_count = 0; struct eventblk *neweblk (); #define add_fd(fd) \ { \ if ((fd) >= acl_nfds) \ acl_nfds = (fd) + 1; \ if (acl_count++ == 0) \ FD_ZERO (&acl_mask); \ FD_SET (fd, &acl_mask); \ } #define del_fd(fd) \ { \ if ((fd) + 1 == acl_nfds) \ acl_nfds--; \ if (--acl_count == 0) \ acl_nfds = 0; \ FD_CLR (fd, &acl_mask); \ } static int acl_nfds = 0; static int acl_count = 0; static fd_set acl_mask; static int qw_nfds = 0; static int qw_count = 0; static fd_set qw_mask; int startlb (), uniqlb (); /* \f */ #ifdef TCP int tcplisten (), tcpaccept1 (), tcpaccept2 (), tcpunique (); #endif #ifdef X25 int x25listen (), x25accept1 (), x25accept2 (), x25unique (); #endif #ifdef BRIDGE_X25 int bridgelisten (), bridgeaccept1 (), bridgeaccept2 (), bridgeunique (); int close_bridge_socket (), bridge_except (); #endif #ifdef TP4 int tp4listen (), tp4accept1 (), tp4accept2 (), tp4unique (); #endif static struct nsapent { int ns_type; int ns_stack; IFP ns_listen; IFP ns_accept1; IFP ns_accept2; IFP ns_unique; IFP ns_close; } nsaps[] = { #ifdef TCP NA_TCP, TS_TCP, tcplisten, tcpaccept1, tcpaccept2, tcpunique, close_tcp_socket, #endif #ifdef X25 NA_X25, TS_X25, x25listen, x25accept1, x25accept2, x25unique, close_x25_socket, #endif #ifdef BRIDGE_X25 NA_BRG, TS_BRG, bridgelisten, bridgeaccept1, bridgeaccept2, bridgeunique, close_bridge_socket, #endif #ifdef TP4 NA_NSAP, TS_TP4, tp4listen, tp4accept1, tp4accept2, tp4unique, close_tp4_socket, #endif NULL }; #ifdef LPP static int _lpp_fd = NOTOK; u_short _lpp_lastport; /* MOBY HACK */ #endif #ifdef BSD42 static int chldhit; SFD chldser (); #endif extern int errno; /* \f */ int TNetListen (ta, td) register struct TSAPaddr *ta; struct TSAPdisconnect *td; { return TNetWork (ta, td, startlb, NULLIFP); } int TNetListenAux (ta, magic, td) register struct TSAPaddr *ta; IFP magic; struct TSAPdisconnect *td; { return TNetWork (ta, td, startlb, magic); } int TNetUnique (ta, td) register struct TSAPaddr *ta; struct TSAPdisconnect *td; { return TNetWork (ta, td, uniqlb, NULLIFP); } /* \f */ static int TNetWork (ta, td, fnx, magic) register struct TSAPaddr *ta; struct TSAPdisconnect *td; IFP fnx; IFP magic; { register int n; int lstn = NOTOK; int fd; register struct NSAPaddr *na; register struct nsapent *ns; struct TSAPdisconnect tds; #ifdef MGMT struct TSAPaddr tas; register struct NSAPaddr *ca; #endif if ((n = ta -> ta_naddr) > NTADDR) return tsaplose (td, DR_PARAMETER, NULLCP, "illegal number of network addresses"); if (n == 0) { if (fnx == startlb) { for (ns = nsaps; ns -> ns_listen; ns++) if (ns -> ns_type == NA_NSAP && (ns -> ns_stack & ts_stacks)) break; if (!ns -> ns_listen) return tsaplose (td, DR_PARAMETER, NULLCP, "unsupported network address (%d)", NA_NSAP); fd = (*fnx) (ta, NULLNA, ns, magic, td); #ifdef MGMT if (fd == OK) (void) TManGen (STARTLISTEN, NULLBP, ta); #endif return fd; } na = ta -> ta_addrs; for (ns = nsaps; ns -> ns_listen; ns++) if (ns -> ns_stack & ts_stacks) { na -> na_type = ns -> ns_type; na++; } if ((n = ta -> ta_naddr = na - ta -> ta_addrs) == 0) return tsaplose (td, DR_PARAMETER, NULLCP, "no transport stacks active!?!"); } #ifdef MGMT bzero ((char *) &tas, sizeof tas); if (tas.ta_selectlen = ta -> ta_selectlen) bcopy (ta -> ta_selector, tas.ta_selector, ta -> ta_selectlen); ca = tas.ta_addrs; #endif for (na = ta -> ta_addrs; n-- > 0; na++) { for (ns = nsaps; ns -> ns_listen; ns++) if (ns -> ns_type == na -> na_type && (ns -> ns_stack & ts_stacks)) break; if (!ns -> ns_listen) continue; if ((fd = (*fnx) (ta, na, ns, magic, td)) == NOTOK) goto out; lstn = OK; #ifdef MGMT *ca++ = *na; /* struct copy */ #endif } if (lstn == OK) { #ifdef MGMT tas.ta_naddr = ca - tas.ta_addrs; (void) TManGen (STARTLISTEN, NULLBP, &tas); #endif return OK; } (void) tsaplose (td, DR_PARAMETER, NULLCP, "no supported network addresses"); out: ; (void) TNetClose (ta, &tds); return NOTOK; } /* \f */ static int startlb (ta, na, ns, magic, td) register struct TSAPaddr *ta; register struct NSAPaddr *na; register struct nsapent *ns; IFP magic; struct TSAPdisconnect *td; { struct TSAPaddr tas; register struct listenblk *lb; bzero ((char *) &tas, sizeof tas); bcopy (ta -> ta_selector, tas.ta_selector, tas.ta_selectlen = ta -> ta_selectlen); if (na) { tas.ta_naddr = 1; tas.ta_addrs[0] = *na; /* struct copy */ } ta = &tas; if (lb = findlblk (ta, LB_LISTEN)) return tsaplose (td, DR_OPERATION, NULLCP, "already listening on %s", taddr2str (ta)); if ((lb = newlblk (LB_LISTEN, ta)) == NULLLBP) return tsaplose (td, DR_CONGEST, NULLCP, NULLCP); lb -> lb_accept1 = ns -> ns_accept1; lb -> lb_accept2 = ns -> ns_accept2; lb -> lb_close = ns -> ns_close; lb -> lb_magic = magic; if ((lb -> lb_fd = (*ns -> ns_listen) (lb, ta, td)) == NOTOK) { freelblk (lb); return NOTOK; } else if (lb -> lb_fd == LISTEN_EXCEPTED) lb -> lb_fd = NOTOK; else add_fd (lb -> lb_fd); return OK; } /* \f */ static int uniqlb (ta, na, ns, magic, td) register struct TSAPaddr *ta; register struct NSAPaddr *na; register struct nsapent *ns; IFP magic; struct TSAPdisconnect *td; { int fd; struct TSAPaddr tas; register struct listenblk *lb; bzero ((char *) &tas, sizeof tas); bcopy (ta -> ta_selector, tas.ta_selector, tas.ta_selectlen = ta -> ta_selectlen); tas.ta_naddr = 1; tas.ta_addrs[0] = *na; /* struct copy */ if ((fd = (*ns -> ns_unique) (&tas, td)) == NOTOK) return NOTOK; bcopy (tas.ta_selector, ta -> ta_selector, ta -> ta_selectlen = tas.ta_selectlen); *na = tas.ta_addrs[0]; /* struct copy */ ta = &tas; if ((lb = newlblk (LB_LISTEN, ta)) == NULLLBP) return tsaplose (td, DR_CONGEST, NULLCP, NULLCP); lb -> lb_fd = fd; lb -> lb_magic = magic; lb -> lb_accept1 = ns -> ns_accept1; lb -> lb_accept2 = ns -> ns_accept2; lb -> lb_close = ns -> ns_close; add_fd (lb -> lb_fd); return OK; } /* \f */ int TNetAcceptAux (vecp, vec, newfd, ta, nfds, rfds, wfds, efds, secs, td) int *vecp; char **vec; int *newfd; struct TSAPaddr *ta; int nfds; fd_set *rfds, *wfds, *efds; int secs; struct TSAPdisconnect *td; { int accepted, fd, fd2, n, xsecs; fd_set ifds, ofds, xfds; register struct listenblk *lb, *lb2; static int inited = 0; if (!inited) { #ifdef BSD42 (void) signal (SIGCHLD, chldser); #else (void) signal (SIGCLD, SIG_IGN); #endif if (acl_count == 0) FD_ZERO (&acl_mask); if (qw_count == 0) FD_ZERO (&qw_mask); inited = 1; } *vecp = 0; *vec = NULL; if (ta) bzero ((char *) ta, sizeof *ta); if (newfd) *newfd = NOTOK; if (acl_count == 0 && ev_count == 0 && qw_count == 0) { if ((n = xselect (nfds, rfds, wfds, efds, secs)) == NOTOK) (void) tsaplose (td, DR_CONGEST, "failed", "xselect"); return n; } if (acl_nfds >= nfds) nfds = acl_nfds + 1; ifds = acl_mask; if (rfds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, rfds)) FD_SET (fd, &ifds); if (qw_nfds >= nfds) nfds = qw_nfds + 1; ofds = qw_mask; if (wfds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, wfds)) FD_SET (fd, &ofds); FD_ZERO (&xfds); if (efds) xfds = *efds; /* struct copy */ for (;;) { xsecs = secs; if (ev_count) { if (secs == NOTOK) xsecs = 60; /* infinite timeout, arrange for periodic */ else check_events (); /* single attempt */ } #ifdef BSD42 chldhit = 0; #endif switch (n = xselect (nfds, &ifds, &ofds, efds, xsecs)) { case OK: if (secs == NOTOK && ev_count) { /* just a timeout */ check_events (); goto next; } empty: ; if (rfds) FD_ZERO (rfds); if (wfds) FD_ZERO (wfds); if (efds) FD_ZERO (efds); return OK; case NOTOK: #ifdef BSD42 if (errno == EINTR && chldhit) goto next; #endif return tsaplose (td, DR_CONGEST, "failed", "xselect"); default: accepted = 0; for (lb = LHead -> lb_forw; lb != LHead; ) { lb = (lb2 = lb) -> lb_forw; if ((fd = lb2 -> lb_fd) == NOTOK) continue; #ifndef LPP if (lb2 -> lb_type == LB_QUEUED) { if (FD_ISSET (fd, &ofds)) { if (TDoQueues (lb2, td) == NOTOK) { if (rfds && FD_ISSET (fd, rfds)) { /* on error, force caller to look at it */ FD_ZERO (rfds); FD_SET (fd, rfds); if (wfds) FD_ZERO (wfds); if (efds) FD_ZERO (efds); return 1; } SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("unable to propagate failure of queued write")); return NOTOK; } FD_CLR (fd, &ofds); } continue; } #endif if (FD_ISSET (fd, &ifds)) { FD_CLR (fd, &ifds); switch (lb2 -> lb_type) { case LB_LISTEN: errno = 0; if ((fd2 = (*lb2 -> lb_accept1) (lb2, td)) == NOTOK) { if (errno == EWOULDBLOCK) continue; return NOTOK; } if ((lb2 = findlblkbyfd (fd2)) == NULL) break; if (lb2 -> lb_type != LB_ACCEPTNOW) break; fd = fd2; /* else fall */ case LB_ACCEPT: { /* take care - lb2 is free'd by accept2 */ IFP closefnx = lb2 -> lb_close, magicfnx = lb2 -> lb_magic; if (ta) *ta = lb2 -> lb_addr; /* struct copy */ if ((*lb2 -> lb_accept2) (lb2, vecp, vec, td) == NOTOK) return NOTOK; if (newfd) *newfd = fd; if (magicfnx && (*magicfnx) (vecp, vec, td) == NOTOK) { (void) (*closefnx) (fd); return NOTOK; } accepted++; } break; case LB_EXCEPTION: if (exception (lb2, td) == NOTOK) return NOTOK; break; default: return tsaplose (td, DR_UNKNOWN, NULLCP, "invalid block type"); } } } if (!accepted) { for (fd = 0 ; fd < nfds; fd++) if (FD_ISSET (fd, &ifds) || FD_ISSET (fd, &ofds) || (efds && FD_ISSET (fd, efds))) break; if (fd >= nfds) { if (secs != NOTOK) goto empty; goto next; } } if (rfds) *rfds = ifds; /* struct copy */ if (wfds) *wfds = ofds; /* struct copy */ return n; } next: ; if (acl_nfds >= nfds) nfds = acl_nfds + 1; ifds = acl_mask; if (rfds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, rfds)) FD_SET (fd, &ifds); if (qw_nfds >= nfds) nfds = qw_nfds + 1; ofds = qw_mask; if (wfds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, wfds)) FD_SET (fd, &ofds); if (efds) *efds = xfds; } } /* \f */ static int exception (lb, td) struct listenblk *lb; struct TSAPdisconnect *td; { register struct listenblk *lb2; register struct eventblk *eb; if ((lb2 = findlblk (&lb -> lb_addr, LB_LISTEN)) != NULLLBP) freelblk (lb2); if ((eb = neweblk (&lb -> lb_addr)) == NULLEVP) return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); eb -> ev_eventfnx = lb -> lb_except; SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("exception on %s", taddr2str (&lb -> lb_addr))); freelblk (lb); return OK; } static check_events () { register struct eventblk *eb, *ep; struct TSAPdisconnect tds; for (eb = EHead -> ev_forw; eb != EHead; eb = ep) { ep = eb -> ev_forw; (void) (*eb -> ev_eventfnx) (eb, &tds); } } /* \f */ int TNetClose (ta, td) register struct TSAPaddr *ta; struct TSAPdisconnect *td; { register struct listenblk *lb, *lp; if (ta == NULLTA) { if (once_only == 0) return OK; for (lb = LHead -> lb_forw; lb != LHead; lb = lp) { lp = lb -> lb_forw; freelblk (lb); } } else { if (ta -> ta_naddr > 1) { int gotone; register int n = ta -> ta_naddr; register struct NSAPaddr *na = ta -> ta_addrs; struct TSAPaddr tas; tas = *ta; /* struct copy */ tas.ta_naddr = 1; gotone = 0; for (na = ta -> ta_addrs, n = ta -> ta_naddr; n > 0; na++, n--) { tas.ta_addrs[0] = *na; /* struct copy */ if (lb = findlblk (&tas, LB_LISTEN)) { freelblk (lb); gotone = 1; } } if (!gotone) return tsaplose (td, DR_PARAMETER, NULLCP, "no such transport addressess"); return OK; } if ((lb = findlblk (ta, LB_LISTEN)) == NULLLBP) return tsaplose (td, DR_PARAMETER, NULLCP, "no such transport addressess"); freelblk (lb); } return OK; } /* \f */ #ifdef BSD42 #include <sys/wait.h> /* ARGSUSED */ static SFD chldser (sig, code, sc) int sig; long code; struct sigcontext *sc; { union wait status; while (wait3 (&status, WNOHANG, (struct rusage *) NULL) > 0) chldhit = 1; } #endif /* \f */ #ifdef LPP /* ARGSUSED */ #endif int TNetFork (vecp, vec, td) int vecp; char **vec; struct TSAPdisconnect *td; { int pid; #ifdef TIOCNOTTY int sd; #endif switch (pid = fork ()) { case OK: break; case NOTOK: (void) tsaplose (td, DR_CONGEST, "connection", "unable to fork, so rejecting"); default: #ifndef LPP { struct TSAPstart tss; register struct TSAPstart *ts = &tss; register struct tsapblk *tb; if (TInit (vecp, vec, ts, td) == NOTOK) { SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("TNetFork: TInit returns [%s]", TErrString (td -> td_reason))); return pid; } if ((tb = findtblk (ts -> ts_sd)) == NULL) { SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("TNetFork: findtblk fails")); return pid; } (void) (*tb -> tb_closefnx) (tb -> tb_fd); tb -> tb_fd = NOTOK; freetblk (tb); } #else if (_lpp_fd != NOTOK) { (void) close_tcp_socket (_lpp_fd); _lpp_fd = NOTOK; } #endif return pid; } (void) TNetClose (NULLTA, td); #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 #ifdef BSD42 (void) signal (SIGCHLD, SIG_DFL); #else (void) signal (SIGCLD, SIG_DFL); #endif return OK; } /* \f TCP */ #ifdef TCP static int tcplisten (lb, ta, td) register struct listenblk *lb; register struct TSAPaddr *ta; struct TSAPdisconnect *td; { int fd; register struct sockaddr_in *isock = &lb -> lb_loc_isock; register struct hostent *hp; register struct NSAPaddr *na; if (ta -> ta_naddr < 1) return tsaplose (td, DR_ADDRESS, NULLCP, "TCP address not specified"); na = ta -> ta_addrs; if (na -> na_domain[0]) { if ((hp = gethostbystring (na -> na_domain)) == NULL) return tsaplose (td, DR_ADDRESS, NULLCP, "%s: unknown host", na -> na_domain); } else hp = NULL; if (na -> na_port == 0) return tsaplose (td, DR_ADDRESS, NULLCP, "TCP port not specified"); bzero ((char *) isock, sizeof *isock); isock -> sin_family = hp ? hp -> h_addrtype : AF_INET; isock -> sin_port = na -> na_port; if (hp) inaddr_copy (hp, isock); switch (na -> na_tset) { #ifdef LPP case NA_TSET_UDP: if ((fd = start_udp_server (isock, 0, 0, 0)) == NOTOK) return tsaplose (td, DR_CONGEST, "failed", "start_udp_server"); break; #endif case NA_TSET_TCP: default: if ((fd = start_tcp_server (isock, SOMAXCONN, 0, 0)) == NOTOK) return tsaplose (td, DR_CONGEST, "failed", "start_tcp_server"); break; } lb -> lb_addr.ta_addrs -> na_tset = na -> na_tset; return fd; } /* \f */ #ifdef LPP char *udpsave (); #endif static int tcpaccept1 (lb, td) register struct listenblk *lb; struct TSAPdisconnect *td; { int fd, tset = lb -> lb_addr.ta_addrs -> na_tset; struct listenblk *lb2; register struct tsapblk *tb = NULL; #ifndef LPP register struct tsapkt *t = NULL; #endif if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } switch (tset) { #ifdef LPP case NA_TSET_UDP: if ((fd = join_udp_client (lb -> lb_fd, &lb2 -> lb_rem_isock)) == NOTOK) { freelblk (lb2); return tsaplose (td, DR_NETWORK, "failed", "join_udp_client"); } break; #endif case NA_TSET_TCP: default: if ((fd = join_tcp_client (lb -> lb_fd, &lb2 -> lb_rem_isock)) == NOTOK) { freelblk (lb2); return tsaplose (td, DR_NETWORK, "failed", "join_tcp_client"); } #ifdef LPP _lpp_fd = fd; _lpp_lastport = lb -> lb_loc_isock.sin_port; #endif #ifdef EXOS del_fd (lb -> lb_fd); if ((lb -> lb_fd = start_tcp_server (&lb -> lb_loc_isock, SOMAXCONN, 0, 0)) != NOTOK) { add_fd (lb -> lb_fd); } #endif break; } lb2 -> lb_fd = fd; lb2 -> lb_addr = lb -> lb_addr; lb2 -> lb_loc_isock = lb -> lb_loc_isock; lb2 -> lb_accept2 = lb -> lb_accept2; lb2 -> lb_close = lb -> lb_close; lb2 -> lb_magic = lb -> lb_magic; #ifndef LPP if ((tb = newtblk ()) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } tb -> tb_fd = fd; (void) TTService (tb); add_fd (fd); #else lb2 -> lb_type = LB_ACCEPTNOW; #endif lb2 -> lb_tb = tb; return fd; out: ; #ifndef LPP if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } freetpkt (t); #endif if (lb2) freelblk (lb2); return NOTOK; } /* \f */ static int tcpaccept2 (lb, vecp, vec, td) register struct listenblk *lb; int *vecp; char **vec; struct TSAPdisconnect *td; { int fd; #ifdef LPP int tset = lb -> lb_addr.ta_addrs -> na_tset; #endif char buffer1[BUFSIZ], buffer2[BUFSIZ]; #ifdef SOCKETS struct sockaddr_in in_socket; struct sockaddr_in *isock = &in_socket; int len; #endif #ifndef LPP register struct tsapblk *tb = lb -> lb_tb; register struct tsapkt *t = NULL; #endif fd = lb -> lb_fd; (void) strcpy (buffer1, inet_ntoa (lb -> lb_rem_isock.sin_addr)); #ifdef SOCKETS len = sizeof *isock; if (getsockname (fd, (struct sockaddr *) isock, &len) != NOTOK) { (void) strcpy (buffer2, inet_ntoa (isock -> sin_addr)); } else #endif (void) strcpy (buffer2, TLocalHostName ()); #ifndef LPP if ((t = fd2tpkt (fd, tb -> tb_initfnx, tb -> tb_readfnx)) == NULL || t -> t_errno != OK) { (void) tpktlose (tb, td, t ? t -> t_errno : DR_CONGEST, NULLCP, NULLCP); goto out; } if (TPDU_CODE (t) != TPDU_CR) { (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, "transport protocol mangled: expecting 0x%x, got 0x%x", TPDU_CR, TPDU_CODE (t)); goto out; } vec[0] = "tsaplisten"; /* any value will do */ if ((vec[1] = tcpsave (fd, &lb -> lb_rem_isock, buffer1, buffer2, td)) == NULL) goto out; if ((vec[2] = tpkt2str (t)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP); goto out; } vec[*vecp = 3] = NULLCP; tb -> tb_fd = NOTOK; freetblk (tb); freetpkt (t); del_fd (lb -> lb_fd); #else vec[0] = "psaplisten"; switch (tset) { case NA_TSET_UDP: if ((vec[1] = udpsave (fd, &lb -> lb_rem_isock, buffer1, buffer2, td)) == NULL) goto out; break; case NA_TSET_TCP: default: if ((vec[1] = tcpsave (fd, &lb -> lb_rem_isock, buffer1, buffer2, td)) == NULL) goto out; break; } vec[*vecp = 2] = NULLCP; #endif lb -> lb_fd = NOTOK; freelblk (lb); return OK; out: ; #ifndef LPP if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } freetpkt (t); del_fd (fd); #endif if (lb) freelblk (lb); return NOTOK; } /* \f */ static int tcpunique (ta, td) register struct TSAPaddr *ta; struct TSAPdisconnect *td; { int fd; char *cp; struct sockaddr_in in_socket; register struct sockaddr_in *isock = &in_socket; register struct hostent *hp; register struct NSAPaddr *na = ta -> ta_addrs; cp = na -> na_domain[0] ? na -> na_domain : TLocalHostName (); if ((hp = gethostbystring (cp)) == NULL) return tsaplose (td, DR_ADDRESS, NULLCP, "%s: unknown host", cp); bzero ((char *) isock, sizeof *isock); isock -> sin_family = hp -> h_addrtype; inaddr_copy (hp, isock); switch (na -> na_tset) { #ifdef LPP case NA_TSET_UDP: if ((fd = start_udp_server (isock, 0, 0, 0)) == NOTOK) return tsaplose (td, DR_CONGEST, "failed", "start_udp_server"); break; #endif case NA_TSET_TCP: default: if ((fd = start_tcp_server (isock, SOMAXCONN, 0, 0)) == NOTOK) return tsaplose (td, DR_CONGEST, "failed", "start_tcp_server"); break; } (void) strcpy (na -> na_domain, inet_ntoa (isock -> sin_addr)); na -> na_port = isock -> sin_port; return fd; } #endif /* \f X.25 */ #ifdef X25 /* ARGSUSED */ static int x25listen (lb, ta, td) struct listenblk *lb; struct TSAPaddr *ta; struct TSAPdisconnect *td; { int fd; if (ta -> ta_naddr < 1) return tsaplose (td, DR_ADDRESS, NULLCP, "X.121 DTE not specified"); if ((fd = start_x25_server (ta -> ta_addrs, SOMAXCONN, 0, SO_KEEPALIVE)) == NOTOK) return tsaplose (td, DR_CONGEST, "failed", "start_x25_server"); lb -> lb_loc_xsock = *ta -> ta_addrs; return fd; } /* \f */ static int x25accept1 (lb, td) register struct listenblk *lb; struct TSAPdisconnect *td; { int fd; register struct tsapblk *tb; struct listenblk *lb2; if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) { tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } lb2 -> lb_accept2 = lb -> lb_accept2; lb2 -> lb_addr = lb -> lb_addr; lb2 -> lb_close = lb -> lb_close; lb2 -> lb_loc_xsock = lb -> lb_loc_xsock; lb2 -> lb_magic = lb -> lb_magic; if ((fd = join_x25_client (lb -> lb_fd, &lb2 -> lb_rem_xsock)) == NOTOK) { freelblk (lb2); return tsaplose (td, DR_NETWORK, "failed", "join_x25_client"); } lb2 -> lb_fd = fd; if ((tb = newtblk ()) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } tb -> tb_fd = fd; (void) XTService (tb); lb2 -> lb_tb = tb; add_fd (fd); return fd; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } if (lb2) freelblk (lb2); return NOTOK; } /* \f */ static int x25accept2 (lb, vecp, vec, td) register struct listenblk *lb; int *vecp; char **vec; struct TSAPdisconnect *td; { register struct tsapblk *tb = lb -> lb_tb; register struct tsapkt *t = NULL; int fd; if ((t = fd2tpkt (fd = tb -> tb_fd, tb -> tb_initfnx, tb -> tb_readfnx)) == NULL || t -> t_errno != OK) { (void) tpktlose (tb, td, t ? t -> t_errno : DR_CONGEST, NULLCP, NULLCP); goto out; } if (TPDU_CODE (t) != TPDU_CR) { (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, "transport protocol mangled: expecting 0x%x, got 0x%x", TPDU_CR, TPDU_CODE (t)); goto out; } vec[0] = "tsaplisten"; /* any value will do */ if ((vec[1] = x25save (fd, lb -> lb_rem_xsock.na_dte, lb -> lb_rem_xsock.na_dtelen, lb -> lb_loc_xsock.na_dte, lb -> lb_loc_xsock.na_dtelen, td)) == NULL) goto out; if ((vec[2] = tpkt2str (t)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP); goto out; } vec[*vecp = 3] = NULLCP; tb -> tb_fd = NOTOK; freetblk (tb); freetpkt (t); lb -> lb_fd = NOTOK; del_fd (fd); freelblk (lb); return fd; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } freetpkt (t); freelblk (lb); del_fd (fd); return NOTOK; } /* \f */ static int x25unique (ta, td) struct TSAPaddr *ta; struct TSAPdisconnect *td; { int fd; register struct NSAPaddr *na = ta -> ta_addrs; bzero ((char *) na, sizeof *na); na -> na_type = NA_X25; if ((fd = start_x25_server (na, SOMAXCONN, 0, SO_KEEPALIVE)) == NOTOK) return tsaplose (td, DR_CONGEST, "failed", "start_x25_server"); return fd; } #endif /* \f */ #ifdef BRIDGE_X25 /* ARGSUSED */ static int bridgelisten (lb, ta, td) register struct listenblk *lb; register struct TSAPaddr *ta; struct TSAPdisconnect *td; { int fd; register struct eventblk *eb; if ((fd = bridgelisten_aux (lb, ta, td)) != NOTOK) return fd; if ((eb = neweblk (ta)) == NULLEVP) return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); eb -> ev_eventfnx = bridge_except; return LISTEN_EXCEPTED; } static int bridge_except (eb, td) register struct eventblk *eb; struct TSAPdisconnect *td; { register struct listenblk *lb; register struct TSAPaddr *ta = &eb -> ev_taddr; if ((lb = newlblk (LB_LISTEN, ta)) == NULLLBP) return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); if ((lb -> lb_fd = bridgelisten_aux (lb, ta, td)) == NOTOK) { freelblk (lb); return OK; } SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("reconnection on %s", taddr2str (ta))); freeeblk (eb); lb -> lb_close = close_bridge_socket; lb -> lb_accept1 = bridgeaccept1; lb -> lb_accept2 = bridgeaccept2; add_fd (lb -> lb_fd); return OK; } static int bridgelisten_aux (lb, ta, td) register struct listenblk *lb; register struct TSAPaddr *ta; struct TSAPdisconnect *td; { int fd; register struct listenblk *lb2; if (ta -> ta_naddr < 1) return tsaplose (td, DR_ADDRESS, NULLCP, "X.121 DTE not specified"); if ((fd = start_bridge_server (ta -> ta_addrs, SOMAXCONN, 0, SO_KEEPALIVE)) == NOTOK) return tsaplose (td, DR_CONGEST, "failed", "start_bridge_server"); lb -> lb_loc_xsock = *ta -> ta_addrs; if ((lb2 = newlblk (LB_EXCEPTION, ta)) == NULLLBP) { close_bridge_socket (fd); return NOTOK; } lb2 -> lb_fd = get_bridge_assfd (fd); lb2 -> lb_except = bridge_except; lb2 -> lb_close = close_bridge_socket; add_fd (lb2 -> lb_fd); return fd; } /* \f */ static int bridgeaccept1 (lb, td) register struct listenblk *lb; struct TSAPdisconnect *td; { int fd; register struct tsapblk *tb; register struct tsapkt *t = NULL; struct listenblk *lb2; if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } lb2 -> lb_accept2 = lb -> lb_accept2; lb2 -> lb_addr = lb -> lb_addr; lb2 -> lb_close = lb -> lb_close; lb2 -> lb_loc_xsock = lb -> lb_loc_xsock; lb2 -> lb_magic = lb -> lb_magic; if ((fd = join_bridge_client (lb -> lb_fd, &lb2 -> lb_rem_xsock)) == NOTOK) { freelblk (lb2); return tsaplose (td, DR_NETWORK, "failed", "join_bridge_client"); } lb2 -> lb_fd = fd; if ((tb = newtblk ()) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } lb2 -> lb_tb = tb; tb -> tb_fd = fd; (void) BTService (tb); add_fd (fd); return fd; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } if (lb2) freelblk (lb2); freetpkt (t); return NOTOK; } /* \f */ static int bridgeaccept2 (lb, vecp, vec, td) register struct listenblk *lb; int *vecp; char **vec; struct TSAPdisconnect *td; { int fd = lb -> lb_fd; register struct tsapblk *tb = lb -> lb_tb; register struct tsapkt *t = NULL; if ((t = fd2tpkt (tb -> tb_fd, tb -> tb_initfnx, tb -> tb_readfnx)) == NULL || t -> t_errno != OK) { (void) tpktlose (tb, td, t ? t -> t_errno : DR_CONGEST, NULLCP, NULLCP); goto out; } if (TPDU_CODE (t) != TPDU_CR) { (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, "transport protocol mangled: expecting 0x%x, got 0x%x", TPDU_CR, TPDU_CODE (t)); goto out; } vec[0] = "tsaplisten"; /* any value will do */ if ((vec[1] = bridgesave (tb -> tb_fd, lb -> lb_rem_xsock.na_dte, lb -> lb_rem_xsock.na_dtelen, lb -> lb_loc_xsock.na_dte, lb -> lb_loc_xsock.na_dtelen, td)) == NULL) goto out; if ((vec[2] = tpkt2str (t)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP); goto out; } vec[*vecp = 3] = NULLCP; tb -> tb_fd = NOTOK; freetblk (tb); freetpkt (t); del_fd (fd); lb -> lb_fd = NOTOK; freelblk (lb); return fd; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } freetpkt (t); freelblk (lb); del_fd (fd); return NOTOK; } /* \f */ /* ARGSUSED */ static int bridgeunique (ta, td) struct TSAPaddr *ta; struct TSAPdisconnect *td; { return tsaplose (td, DR_ADDRESS, NULLCP, "unique listens not supported at the X.25 bridge"); } #endif /* \f TP4 */ #ifdef TP4 /* \f TP4 from 4.4BSD */ #ifdef BSD_TP4 /* ARGSUSED */ static int tp4listen (lb, ta, td) struct listenblk *lb; register struct TSAPaddr *ta; struct TSAPdisconnect *td; { return start_tp4_server (ta, SOMAXCONN, SO_KEEPALIVE, 0, td); } /* \f */ static int tp4accept1 (lb, td) register struct listenblk *lb; struct TSAPdisconnect *td; { int fd; register struct tsapblk *tb; struct listenblk *lb2; if ((lb2 = newlblk (LB_ACCEPTNOW, NULLTA)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } lb2 -> lb_accept2 = lb -> lb_accept2; lb2 -> lb_addr = lb -> lb_addr; lb2 -> lb_close = lb -> lb_close; lb2 -> lb_loc_tsock = lb -> lb_loc_tsock; if ((fd = join_tp4_client (lb -> lb_fd, &lb2 -> lb_rem_tsock, td)) == NOTOK) { freelblk (lb2); return NOTOK; } lb2 -> lb_fd = fd; if ((tb = newtblk ()) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } tb -> tb_fd = fd; (void) tp4init (tb); lb2 -> lb_tb = tb; tb -> tb_responding = lb2 -> lb_rem_tsock; /* struct copy */ return fd; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } if (lb2) freelblk (lb2); return NOTOK; } /* \f */ static int tp4accept2 (lb, vecp, vec, td) register struct listenblk *lb; int *vecp; char **vec; struct TSAPdisconnect *td; { int cc, fd = lb -> lb_fd, len; char udata[TS_SIZE]; register struct tsapblk *tb = lb -> lb_tb; struct sockaddr_osi sock; struct sockaddr_iso *ifaddr = &sock.osi_sockaddr; static char buffer[BUFSIZ]; len = sizeof sock; if (getsockname (fd, (struct sockaddr *) ifaddr, &len) != NOTOK) { ifaddr -> siso_len = len; (void) tp42gen (&tb -> tb_initiating, &sock); } else SLOG (tsap_log, LLOG_EXCEPTIONS, "failed", ("getsockname on incoming connection")); cc = sizeof udata; if (getsockopt (fd, SOL_TRANSPORT, TPOPT_CONN_DATA, udata, &cc) == NOTOK) { (void) tsaplose (td, DR_CONGEST, "TPOPT_CONN_DATA", "unable to get"); goto out; } vec[0] = "tsaplisten"; /* any value will do */ if ((vec[1] = tp4save (tb -> tb_fd, td)) == NULL) goto out; len = 0; if (cc > 0) len += explode (buffer + len, (u_char *) udata, cc); buffer[len] = NULL; vec[2] = buffer; vec[*vecp = 3] = NULLCP; tb -> tb_fd = NOTOK; freetblk (tb); lb -> lb_fd = NOTOK; freelblk (lb); return OK; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } freelblk (lb); return NOTOK; } /* \f */ /* ARGSUSED */ static int tp4unique (ta, td) struct TSAPaddr *ta; struct TSAPdisconnect *td; { int fd; register struct NSAPaddr *na = ta -> ta_addrs; bzero ((char *) na, sizeof *na); na -> na_type = NA_NSAP; return start_tp4_server (na, SOMAXCONN, SO_KEEPALIVE, 0, td); } #endif /* \f TP4 from SunLink OSI */ #ifdef SUN_TP4 /* ARGSUSED */ static int tp4listen (lb, ta, td) struct listenblk *lb; register struct TSAPaddr *ta; struct TSAPdisconnect *td; { return start_tp4_server (ta, SOMAXCONN, 0, 0, td); } /* \f */ static int tp4accept1 (lb, td) register struct listenblk *lb; struct TSAPdisconnect *td; { int fd; register struct tsapblk *tb; struct listenblk *lb2; if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } lb2 -> lb_loc_isock = lb -> lb_loc_isock; lb2 -> lb_addr = lb -> lb_addr; lb2 -> lb_accept2 = lb -> lb_accept2; lb2 -> lb_close = lb -> lb_close; lb2 -> lb_magic = lb -> lb_magic; if ((fd = join_tp4_client (lb -> lb_fd, &lb -> lb_rem_tsock, td)) == NOTOK) { freelblk (lb2); return NOTOK; } lb2 -> lb_fd = fd; if ((tb = newtblk ()) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); goto out; } tb -> tb_fd = fd; (void) tp4init (tb); add_fd (fd); lb2 -> lb_tb = tb; return fd; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } if (lb2) freelblk (lb2); return NOTOK; } /* \f */ static int tp4accept2 (lb, vecp, vec, td) register struct listenblk *lb; int *vecp; char **vec; struct TSAPdisconnect *td; { int cc, fd = lb -> lb_fd, header_len, len; char data[TC_SIZE]; register struct tsapblk *tb = lb -> lb_tb; register struct tp4pkt *tp = NULL; static char buffer[BUFSIZ]; if ((tp = newtp4pkt ((TP_EVENT) 0)) == NULL) { (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP); goto out; } header_len = sizeof (TP_MSG_CONNECT); if ((cc = recvfrom (fd, data, sizeof data, 0, (struct sockaddr *) tp, &header_len)) == NOTOK) { (void) tpktlose (tb, td, DR_CONGEST, "failed", "recvfrom"); goto out; } if (tp -> tp4_event != TP_CONNECT_IND) { (void) tpktlose (tb, td, DR_REMOTE, NULLCP, "transport protocol mangled: expecting 0x%x got 0x%x", TP_CONNECT_IND, tp -> tp4_event); goto out; } (void) tp42gen (&tb -> tb_responding, &tp -> tp4_called); (void) tp42gen (&tb -> tb_initiating, &tp -> tp4_calling); vec[0] = "tsaplisten"; /* any value will do */ if ((vec[1] = tp4save (tb -> tb_fd, td)) == NULL) goto out; len = explode (buffer, (u_char *) tp, sizeof (TP_MSG_CONNECT)); if (cc > 0) len += explode (buffer + len, (u_char *) data, cc); buffer[len] = NULL; vec[2] = buffer; vec[*vecp = 3] = NULLCP; tb -> tb_fd = NOTOK; freetblk (tb); freetp4pkt (tp); del_fd (lb -> lb_fd); lb -> lb_fd = NOTOK; freelblk (lb); return OK; out: ; if (tb) { tb -> tb_fd = NOTOK; freetblk (tb); } if (tp) freetp4pkt (tp); freelblk (lb); del_fd (fd); return NOTOK; } /* \f */ /* ARGSUSED */ static int tp4unique (ta, td) struct TSAPaddr *ta; struct TSAPdisconnect *td; { return tsaplose (td, DR_ADDRESS, NULLCP, "unique listens not yet supported with SunLink OSI"); } #endif #endif /* \f INTERNAL */ static struct listenblk *newlblk (type, ta) int type; struct TSAPaddr *ta; { register struct listenblk *lb; lb = (struct listenblk *) calloc (1, sizeof *lb); if (lb == NULLLBP) return lb; lb -> lb_fd = NOTOK; if (ta) lb -> lb_addr = *ta; /* struct copy */ lb -> lb_type = type; if (once_only == 0) { LHead -> lb_forw = LHead -> lb_back = LHead; once_only++; } insque (lb, LHead -> lb_back); return lb; } static freelblk (lb) register struct listenblk *lb; { if (lb == NULLLBP) return; #ifdef MGMT if (lb -> lb_type == LB_LISTEN) (void) TManGen (ENDLISTEN, NULLBP, &lb -> lb_addr); #endif #ifndef LPP if (lb -> lb_type != LB_QUEUED) #endif if (lb -> lb_fd != NOTOK) { del_fd (lb -> lb_fd); (void) (*lb -> lb_close) (lb -> lb_fd); } remque (lb); free ((char *) lb); } /* \f */ static struct listenblk *findlblk (ta, type) register struct TSAPaddr *ta; int type; { register struct listenblk *lb; if (once_only == 0) return NULLLBP; for (lb = LHead -> lb_forw; lb != LHead; lb = lb -> lb_forw) if (lb -> lb_type == type && bcmp ((char *) &lb -> lb_addr, (char *) ta, sizeof *ta) ==0) return lb; return NULLLBP; } static struct listenblk *findlblkbyfd (fd) int fd; { register struct listenblk *lb; if (once_only == 0) return NULLLBP; for (lb = LHead -> lb_forw; lb != LHead; lb = lb -> lb_forw) #ifndef LPP if (lb -> lb_type != LB_QUEUED) #endif if (lb -> lb_fd == fd) return lb; return NULLLBP; } /* \f */ static struct eventblk *neweblk (ta) struct TSAPaddr *ta; { register struct eventblk *eb; eb = (struct eventblk *) calloc (1, sizeof *eb); if (eb == NULLEVP) return eb; eb -> ev_taddr = *ta; /* struct copy */ if (ev_onceonly == 0) { EHead -> ev_forw = EHead -> ev_back = EHead; ev_onceonly++; } insque (eb, EHead -> ev_back); ev_count++; return eb; } #ifdef BRIDGE_X25 static freeeblk (eb) register struct eventblk *eb; { if (eb == NULLEVP) return; remque (eb); free ((char *) eb); ev_count--; } #endif /* \f */ #ifdef LPP #ifdef lint /* VARARGS */ int tsaplose (td, reason, what, fmt) struct TSAPdisconnect *td; int reason; char *what, *fmt; { return tsaplose (td, reason, what, fmt); } #endif #endif /* \f queued writes */ #ifndef LPP static int TNetQueue (tb, insert, td) register struct tsapblk *tb; int insert; struct TSAPdisconnect *td; { register struct listenblk *lb; if (once_only == 0) { LHead -> lb_forw = LHead -> lb_back = LHead; once_only++; } for (lb = LHead -> lb_forw; lb != LHead; lb = lb -> lb_forw) if (lb -> lb_type == LB_QUEUED && lb -> lb_tb == tb) break; if (!insert) { if (lb != LHead) TFreeQueues (lb); return OK; } if (lb != LHead) /* should "never happen" */ return OK; if ((lb = newlblk (LB_QUEUED, NULLTA)) == NULLLBP) { SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("unable to allocate listenblk for queued writes")); return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); } lb -> lb_fd = (lb -> lb_tb = tb) -> tb_fd; if (lb -> lb_fd >= qw_nfds) qw_nfds = lb -> lb_fd + 1; if (qw_count++ == 0) FD_ZERO (&qw_mask); FD_SET (lb -> lb_fd, &qw_mask); return OK; } /* \f */ static int TDoQueues (lb, td) register struct listenblk *lb; struct TSAPdisconnect *td; { register struct tsapblk *tb = lb -> lb_tb; switch ((*tb -> tb_drainPfnx) (tb, td)) { case NOTOK: return NOTOK; case DONE: default: TFreeQueues (lb); /* and fall... */ case OK: return OK; } } /* \f */ static int TFreeQueues (lb) register struct listenblk *lb; { if (lb -> lb_fd + 1 == qw_nfds) qw_nfds--; if (--qw_count == 0) qw_nfds = 0; FD_CLR (lb -> lb_fd, &qw_mask); lb -> lb_fd = NOTOK; freelblk (lb); } /* \f */ int TSetQueuesOK (sd, onoff, td) int sd; int onoff; struct TSAPdisconnect *td; { int result; SBV smask; register struct tsapblk *tb; missingP (td); smask = sigioblock (); tsapPsig (tb, sd); result = OK; if (onoff) { if (tb -> tb_drainPfnx == NULLIFP) result = tsaplose (td, DR_OPERATION, NULLCP, "queued writes not supported by TS-stack"); else { tb -> tb_flags |= TB_QWRITES; tb -> tb_queuePfnx = TNetQueue; } } else if (tb -> tb_qwrites.qb_forw != &tb -> tb_qwrites) result = tsaplose (td, DR_WAITING, NULLCP, "queued writes still waiting to drain"); else { tb -> tb_flags &= ~TB_QWRITES; tb -> tb_queuePfnx = NULLIFP; } (void) sigiomask (smask); return result; } #endif