|
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 d
Length: 15285 (0x3bb5) Types: TextFile Names: »dgram.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/compat/dgram.c«
/* dgram.c - datagram (CL-mode TS) abstractions */ #ifndef lint static char *rcsid = "$Header: /f/osi/compat/RCS/dgram.c,v 7.5 90/01/11 18:35:03 mrose Exp $"; #endif /* * $Header: /f/osi/compat/RCS/dgram.c,v 7.5 90/01/11 18:35:03 mrose Exp $ * * * $Log: dgram.c,v $ * Revision 7.5 90/01/11 18:35:03 mrose * real-sync * * Revision 7.4 89/12/19 17:57:34 mrose * touch-up * * Revision 7.3 89/12/19 15:15:31 mrose * dgram * * Revision 7.2 89/12/17 18:30:11 mrose * foo * * Revision 7.1 89/12/11 16:22:25 mrose * more dgram * * Revision 7.0 89/12/01 10:42:35 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 "general.h" #include "manifest.h" #include "tailor.h" #include "dgram.h" #ifdef TCP #include "internet.h" #endif #ifdef TP4 #include "tp4.h" #endif #if defined(SOCKETS) && (defined(TCP) || defined(CLTS)) #ifndef DEBUG #define action(s,i) #endif extern int errno; /* \f */ union sockaddr_un { /* 'cause sizeof (struct sockaddr_iso) == 32 */ struct sockaddr sa; #ifdef TCP struct sockaddr_in sin; #endif #ifdef BSD_TP4 union sockaddr_osi sosi; #endif }; struct dgramblk { int dgram_parent; union sockaddr_un dgram_peer; #ifdef BSD44 u_char dgram_addrlen; #endif struct qbuf dgram_queue; }; static int maxpeers = 0; static struct dgramblk *peers = NULL; /* \f */ #ifdef TCP /* ARGSUSED */ int start_udp_server (sock, backlog, opt1, opt2) struct sockaddr_in *sock; int backlog, opt1, opt2; { register int port; int sd; #ifdef BSD43 int onoff; #endif register struct dgramblk *up, *vp; if (peers == NULL) { maxpeers = getdtablesize (); peers = (struct dgramblk *) calloc ((unsigned)maxpeers, sizeof *peers); if (peers == NULL) return NOTOK; for (vp = (up = peers) + maxpeers; up < vp; up++) { up -> dgram_parent = NOTOK; up -> dgram_queue.qb_forw = up -> dgram_queue.qb_back = &up -> dgram_queue; } } if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK) return NOTOK; if (sock -> sin_port != 0) { action ("BIND", (struct sockaddr *) sock); if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK) goto got_socket; (void) close (sd); return NOTOK; } else sock -> sin_family = AF_INET; for (port = IPPORT_RESERVED;; port++) { sock -> sin_port = htons ((u_short) port); action ("BIND", (struct sockaddr *) sock); if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK) break; switch (errno) { case EADDRINUSE: continue; case EADDRNOTAVAIL: default: (void) close (sd); return NOTOK; } } got_socket: ; #ifdef DEBUG { int len = sizeof *sock; action ("FOO1", (struct sockaddr *) sock); if (getsockname (sd, (struct sockaddr *) sock, &len) != NOTOK) action ("FOO2", (struct sockaddr *) sock); } #endif #ifndef BSD43 if (opt1) (void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0); if (opt2) (void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0); #else onoff = 1; if (opt1) (void) setsockopt (sd, SOL_SOCKET, opt1, (char *)&onoff, sizeof onoff); if (opt2) (void) setsockopt (sd, SOL_SOCKET, opt2, (char *)&onoff, sizeof onoff); #endif return (peers[sd].dgram_parent = sd); } #endif /* \f */ #ifdef BSD_TP4 /* ARGSUSED */ int start_clts_server (sock, backlog, opt1, opt2) union sockaddr_osi *sock; int backlog, opt1, opt2; { int sd; #ifdef BSD43 int onoff; #endif u_char *cp; register struct dgramblk *up, *vp; struct sockaddr_iso *ifaddr = &sock -> osi_sockaddr; if (peers == NULL) { maxpeers = getdtablesize (); peers = (struct dgramblk *) calloc ((unsigned)maxpeers, sizeof *peers); if (peers == NULL) return NOTOK; for (vp = (up = peers) + maxpeers; up < vp; up++) { up -> dgram_parent = NOTOK; up -> dgram_queue.qb_forw = up -> dgram_queue.qb_back = &up -> dgram_queue; } } if ((sd = socket (AF_ISO, SOCK_DGRAM, 0)) == NOTOK) return NOTOK; if (ifaddr -> siso_tlen != 0) { action ("BIND", (struct sockaddr *) ifaddr); if (bind (sd, (struct sockaddr *) ifaddr, (int) ifaddr -> siso_len) != NOTOK) goto got_socket; (void) close (sd); return NOTOK; } else ifaddr -> siso_family = AF_ISO; { int pid; u_char *dp, *ep, *fp; pid = getpid (); cp = fp = (u_char *) ifaddr -> siso_data + ifaddr -> siso_nlen; for (ep = (dp = (u_char *) &pid) + sizeof pid; dp < ep; dp++) *cp++ = *dp; ifaddr -> siso_tlen = (cp - fp) + 1; ifaddr -> siso_slen = ifaddr -> siso_plen = 0; ifaddr -> siso_len = sizeof *ifaddr; } for (*cp = 0x00; *cp < 0xff; *cp += 1) { action ("BIND", (struct sockaddr *) ifaddr); if (bind (sd, (struct sockaddr *) ifaddr, (int) ifaddr -> siso_len) != NOTOK) goto got_socket; switch (errno) { case EADDRINUSE: continue; case EADDRNOTAVAIL: default: (void) close (sd); return NOTOK; } } (void) close (sd); errno = EADDRNOTAVAIL; return NOTOK; got_socket: ; #ifdef DEBUG { int len = sizeof *sock; action ("FOO1", ifaddr); if (getsockname (sd, (struct sockaddr *) ifaddr, &len) != NOTOK) action ("FOO2", ifaddr); } #endif #ifndef BSD43 if (opt1) (void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0); if (opt2) (void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0); #else onoff = 1; if (opt1) (void) setsockopt (sd, SOL_SOCKET, opt1, (char *)&onoff, sizeof onoff); if (opt2) (void) setsockopt (sd, SOL_SOCKET, opt2, (char *)&onoff, sizeof onoff); #endif return (peers[sd].dgram_parent = sd); } #endif /* \f */ int join_dgram_aux (fd, sock, newfd) int fd, newfd; struct sockaddr *sock; { int nfds, sd; fd_set ifds; register struct qbuf *qb; register struct dgramblk *up; if (fd < 0 || fd >= maxpeers || peers[fd].dgram_parent != fd) { errno = EINVAL; return NOTOK; } if (newfd) { FD_ZERO (&ifds); nfds = fd + 1; FD_SET (fd, &ifds); if (select_dgram_socket (nfds, &ifds, NULLFD, NULLFD, OK) == NOTOK) return NOTOK; up = &peers[fd]; if ((qb = up -> dgram_queue.qb_forw) == &up -> dgram_queue) { errno = EWOULDBLOCK; return NOTOK; } if ((sd = dup (fd)) == NOTOK) return NOTOK; up = &peers[sd]; #ifdef BSD44 bcopy (qb -> qb_base, (caddr_t) sock, ((struct sockaddr *) qb -> qb_base) -> sa_len); #else *sock = *((struct sockaddr *) qb -> qb_base); /* struct copy */ #endif remque (qb); insque (qb, up -> dgram_queue.qb_back); } else up = &peers[fd]; up -> dgram_parent = fd; #ifdef BSD44 if (sock -> sa_len == 0) sock -> sa_len = sizeof *sock; bcopy ((caddr_t) sock, (caddr_t) &up -> dgram_peer, sock -> sa_len); { struct sockaddr_in *sin; up -> dgram_addrlen = sock -> sa_family != AF_INET ? sock -> sa_len : sizeof *sin - sizeof sin -> sin_zero; } #else up -> dgram_peer.sa = *sock; /* struct copy */ #endif action ("JOIN", sock); return (newfd ? sd : OK); } /* \f */ int read_dgram_socket (fd, q) int fd; struct qbuf **q; { int nfds; fd_set ifds, mask; register struct qbuf *qb; register struct dgramblk *up; if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> dgram_parent == NOTOK) { errno = EINVAL; return NOTOK; } if ((qb = up -> dgram_queue.qb_forw) == &up -> dgram_queue) { FD_ZERO (&ifds); nfds = fd + 1; FD_SET (fd, &mask); for (ifds = mask;; ifds = mask) { if (select_dgram_socket (nfds, &ifds, NULLFD, NULLFD, NOTOK) == NOTOK) return NOTOK; if ((qb = up -> dgram_queue.qb_forw) != &up -> dgram_queue) break; } } remque (qb); qb -> qb_forw = qb -> qb_back = qb; *q = qb; return qb -> qb_len; } /* \f */ int hack_dgram_socket (fd, sock) int fd; struct sockaddr *sock; { register struct dgramblk *up; if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> dgram_parent != fd) { errno = EINVAL; return NOTOK; } if (sock == NULL) { bzero ((caddr_t) &up -> dgram_peer, sizeof up -> dgram_peer); return OK; } #ifdef BSD44 if (sock -> sa_len == 0) sock -> sa_len = sizeof *sock; bcopy ((caddr_t) sock, (caddr_t) &up -> dgram_peer, sock -> sa_len); up -> dgram_addrlen = 0; #else up -> dgram_peer.sa = *sock; /* struct copy */ #endif action ("HACK", sock); return OK; } int write_dgram_socket (fd, qb) int fd; register struct qbuf *qb; { register struct dgramblk *up; if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> dgram_parent == NOTOK || up -> dgram_peer.sa.sa_family == 0) { errno = EINVAL; return NOTOK; } action ("SENDTO", &up -> dgram_peer.sa); #ifdef BSD44 return sendto (fd, qb -> qb_data, qb -> qb_len, NULL, &up -> dgram_peer.sa, (int) up -> dgram_peer.sa.sa_len); #else return sendto (fd, qb -> qb_data, qb -> qb_len, NULL, &up -> dgram_peer.sa, sizeof up -> dgram_peer.sa); #endif } /* \f */ int close_dgram_socket (fd) int fd; { register struct dgramblk *up, *vp; if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> dgram_parent == NOTOK) { errno = EINVAL; return NOTOK; } action ("CLOSE", &up -> dgram_peer.sa); up -> dgram_parent = NOTOK; bzero ((char *) &up -> dgram_peer, sizeof up -> dgram_peer); QBFREE (&up -> dgram_queue); for (vp = (up = peers) + maxpeers; up < vp; up++) if (up -> dgram_parent == fd) up -> dgram_parent = up - peers; return close (fd); } /* \f */ int select_dgram_socket (nfds, rfds, wfds, efds, secs) int nfds; fd_set *rfds, *wfds, *efds; int secs; { register int fd; int cc, mfds, result; fd_set ifds, jfds; register struct qbuf *qb; register struct dgramblk *up, *vp; struct dgramblk *wp; union sockaddr_un *sock; if (rfds) { jfds = *rfds; if (secs != OK) for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++) if (up -> dgram_parent != NOTOK && FD_ISSET (fd, &jfds) && up -> dgram_queue.qb_forw != &up -> dgram_queue) { secs = OK; break; } } if ((result = selsocket (nfds, rfds, wfds, efds, secs)) == NOTOK || rfds == NULLFD) return result; ifds = *rfds; if ((mfds = nfds) > maxpeers) mfds = maxpeers; for (fd = 0, up = peers; fd < mfds; fd++, up++) if (FD_ISSET (fd, &ifds)) { int slen; u_char len; char *data; if (up -> dgram_parent == NOTOK) continue; if ((qb = (struct qbuf *) malloc ((unsigned) (sizeof *qb + (slen = sizeof *sock) + MAXDGRAM))) == NULL) return NOTOK; sock = (union sockaddr_un *) qb -> qb_base; qb -> qb_data = qb -> qb_base + slen; if ((cc = recvfrom (fd, qb -> qb_data, MAXDGRAM, NULL, &sock -> sa, &slen)) == NOTOK) { free ((char *) qb); return NOTOK; } #ifdef BSD44 sock -> sa.sa_len = slen; #endif qb -> qb_len = cc; action ("RECVFROM", &sock -> sa); vp = up; data = sock -> sa.sa_data; switch (sock -> sa.sa_family) { case AF_INET: /* XXX: doesn't take into account padding */ len = sizeof sock -> sin - sizeof sock -> sin.sin_zero; break; default: #ifdef BSD44 len = sock -> sa.sa_len; #else len = sizeof sock -> sa; #endif break; } if ( #ifdef BSD44 len != up -> dgram_addrlen || #endif bcmp (data, up -> dgram_peer.sa.sa_data, (int) len) != 0) { for (wp = (vp = peers) + maxpeers; vp < wp; vp++) if (vp != up && vp -> dgram_parent == up -> dgram_parent #ifdef BSD44 && len == vp -> dgram_addrlen #endif && bcmp (data, vp -> dgram_peer.sa.sa_data, (int) len) == 0) break; if (vp >= wp && (vp = &peers[up -> dgram_parent]) -> dgram_peer.sa.sa_family != 0) { free ((char *) qb); continue; } } insque (qb, vp -> dgram_queue.qb_back); } for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++) if (up -> dgram_parent != NOTOK && FD_ISSET (fd, &jfds)) if (up -> dgram_queue.qb_forw != &up -> dgram_queue) FD_SET (fd, rfds); else FD_CLR (fd, rfds); result = 0; ifds = *rfds; if (wfds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, wfds)) FD_SET (fd, &ifds); if (efds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, efds)) FD_SET (fd, &ifds); for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, &ifds)) result++; return result; } /* \f */ #ifdef DEBUG #ifdef TCP #include "isoaddrs.h" static inetprint (sin, bp) struct sockaddr_in *sin; char *bp; { (void) sprintf (bp, "Internet=%s+%d+%d", inet_ntoa (sin -> sin_addr), (int) ntohs (sin -> sin_port), NA_TSET_UDP); } #endif /* \f */ #ifdef CLTS /* prints OSI address using the format described in: "A string encoding of Presentation Address" S.E. Kille, Research Note RN/89/14, February 1989 Department of Computer Science University College London */ #ifndef SSEL #define SSEL(s) ((s)->siso_tlen + TSEL(s)) #define PSEL(s) ((s)->siso_slen + SSEL(s)) #endif static isoprint (siso, bp) register struct sockaddr_iso *siso; char *bp; { int didone = 0; if (siso -> siso_plen) { hexprint (bp, siso -> siso_plen, PSEL (siso), "'", "'H"); bp += strlen (bp); *bp++ = '/'; didone++; } if (siso -> siso_slen || didone) { hexprint (bp, siso -> siso_slen, SSEL (siso), "'", "'H"); bp += strlen (bp); *bp++ = '/'; didone++; } if (siso -> siso_tlen || didone) { hexprint (bp, siso -> siso_tlen, TSEL (siso), "'", "'H"); bp += strlen (bp); *bp++ = '/'; didone++; } hexprint (bp, siso -> siso_nlen, siso -> siso_data, "NS+", ""); } static hexprint (bp, n, buf, start, stop) char *bp; int n; u_char *buf; char *start, *stop; { register u_char *in = buf, *top = in + n; if (n == 0) return; (void) strcpy (bp, start); bp += strlen (bp); while (in < top) { (void) sprintf (bp, "%02x", *in++ & 0xff); bp += 2; } (void) strcpy (bp, stop); } #endif /* \f */ static struct printent { int p_family; IFP p_function; } ents[] = { #ifdef TCP AF_INET, inetprint, #endif #ifdef CLTS AF_ISO, isoprint, #endif NULL }; static action (s, sock) char *s; struct sockaddr *sock; { char buffer[BUFSIZ]; register struct printent *p; if (!(compat_log -> ll_events & LLOG_TRACE)) return; for (p = ents; p -> p_family; p++) if (p -> p_family == sock -> sa_family) break; if (!p -> p_family) { DLOG (compat_log, LLOG_EXCEPTIONS, ("unknown dgram address family 0x%x", sock -> sa_family)); return; } (void) (*p -> p_function) (sock, buffer); DLOG (compat_log, LLOG_TRACE, ("%-10.10s %s", s, buffer)); } #endif #else /* \f */ int dgram_dummy () {} #endif