DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦3b72f3af4⟧ TextFile

    Length: 15285 (0x3bb5)
    Types: TextFile
    Names: »dgram.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/compat/dgram.c« 

TextFile

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