[comp.sources.unix] v20i058: User-level interface to Ethernet, Part01/03

rsalz@uunet.uu.net (Rich Salz) (10/26/89)

Submitted-by: Alexander Dupuy <dupuy@cs.columbia.edu>
Posting-number: Volume 20, Issue 58
Archive-name: etherlib/part01

This ethernet access library is a part of the Columbia Netmate project
which is being released as a useful component in its own right.

These functions provide access to the raw ethernet for user-level
programs.  On Suns, they are implemented using NIT(4p) (network interface
tap).  While they do not provide the full functionality of NIT, these
functions do run on both the socket- and streams-based NIT
implementations.  On Ultrix systems, they are implemented using DLI (data
link interface).  On Berkeley systems, they are implemented using the
Stanford enetfilter available as user-contributed software in the 4.3 BSD
release.

These functions are not designed to be used for ethernet monitoring, but rather
for programs implementing ethernet protocols such as RARP, or the Ethernet
configuration test protocol.

It comes with a manual page, and both a GNU makefile and a regular one.

If you are on a BSD system with the enetfilter, you will have to create
some new device files before you can build or use this library.  Because
there is no way to map between the interface names ("il0", "de0", etc.)
used by most programs and the old enetfilter device names (/dev/enet0,
/dev/eneta0, etc.), this library uses a different convention for
enetfilter device names, using device files in the /dev/enet/ directory.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  ./GNUmake.config ./GNUmakefile ./ReadMe
#   ./src ./src/ReadMe ./src/dliaddr.c ./src/dliintaddr.c
#   ./src/dliread.c ./src/dlireadv.c ./src/dliself.c ./src/dliwrite.c
#   ./src/dliwritev.c ./src/enetaddr.c ./src/enetblock.c
#   ./src/enetintaddr.c ./src/enetself.c ./src/enetwrite.c
#   ./src/enetwritev.c ./src/ethera2e.c ./src/etheraddr.c
#   ./src/etherblock.c ./src/ethere2a.c ./src/etherlocal.c
#   ./src/etherread.c ./src/etherreadv.c ./src/libether.h
#   ./src/nit3intaddr.c ./src/nit3read.c ./src/nit3readv.c
#   ./src/nit3self.c ./src/nit3write.c ./src/nit3writev.c
#   ./src/nit4intaddr.c ./src/nit4self.c ./src/nit4write.c
#   ./src/nit4writev.c ./src/nitaddr.c ./system ./tests MANIFEST
# Wrapped by rsalz@papaya.bbn.com on Wed Oct 25 16:37:29 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './GNUmake.config' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./GNUmake.config'\"
else
echo shar: Extracting \"'./GNUmake.config'\" \(1799 characters\)
sed "s/^X//" >'./GNUmake.config' <<'END_OF_FILE'
X#
X# Build flags which are used by various components
X#
X
Xifeq ($(SYSTEM),)
X
XSYSTEM := $(strip $(shell PATH=$$PATH:.:..:../..:../../.. system ))
X
X
X# Compilation parameters
X# (don't try to use gcc if the machine isn't supported yet)
X# don't use gcc on Sun-4 until we resolve structure pass/return incompatibility
X
Xifneq ($(findstring ibmrt,$(SYSTEM)),ibmrt)
Xifneq ($(findstring mipsel,$(SYSTEM)),mipsel)
Xifneq ($(findstring sun4,$(SYSTEM)),sun4)
XCC := gcc
Xendif
Xendif
Xendif
X
X#
X# Sun-3 floating-point options; replace 68881 with soft or fpa as appropriate
X#
X
Xifeq ($(findstring sun3,$(SYSTEM)),sun3)
X
XFLOAT_OPTION = f68881
X
Xifeq ($(findstring os4,$(SYSTEM)),os4)
X
XFLIB = /usr/lib/$(FLOAT_OPTION).il
X
Xelse
X
XFLIB = /usr/lib/$(FLOAT_OPTION)/libm.il
X
Xendif
X
Xendif
X
XOPT = -g
XOPTG = -g -W
X
Xifeq ($(findstring os4,$(SYSTEM)),os4)
Xifeq ($(findstring -g,$(OPTG)),-g)
Xifeq ($(findstring gcc,$(CC)),gcc)
Xoverride LDFLAGS := -g -static
Xelse
Xoverride LDFLAGS := -g -Bstatic
Xendif
Xendif
Xendif
X
XDEFINES = 
X
X
X# Listing variables and flags
X
XTROFF = ptroff
XVGRIND = vgrind
X
XGRIND = $(VGRIND) -d vgrindefs
X
X
X# Installation tools
X
XINSTALL=install -c
X
Xifeq ($(findstring os4,$(SYSTEM)),os4)
XRANLIB=ranlib -t
Xelse
XRANLIB=ranlib
Xendif
X
X
X# Installation locations
X
XMANDIR = /usr/local/man
XBINDIR = /usr/local/bin
XLIBDIR = /usr/local/lib
XINCDIR = /usr/local/include
X
Xendif
X
X
X# Pattern rules
X
X%.ps: %.c
X	$(VGRIND) -lC -t $< > $@
X
X%.ps: %.h
X	$(VGRIND) -lC -t $< > $@
X
X# Installation pattern rules
X
X%/bin: %
X	mkdir $@
X
X$(BINDIR)/%: %
X	$(INSTALL) $< $@
X
X%/lib: %
X	mkdir $@
X
X$(LIBDIR)/%: %
X	$(INSTALL) $< $@
X	$(RANLIB) $@
X	@chmod -x $@
X
X%/include: %
X	mkdir $@
X
X$(INCDIR)/%: %
X	$(INSTALL) $< $@
X	@chmod -x $@
X
X%/man: %
X	mkdir $@
X
X$(MANDIR)/man1/%: %
X	$(INSTALL) $< $@
X	@chmod -x $@
X
X$(MANDIR)/man3/%: %
X	$(INSTALL) $< $@
X	@chmod -x $@
END_OF_FILE
if test 1799 -ne `wc -c <'./GNUmake.config'`; then
    echo shar: \"'./GNUmake.config'\" unpacked with wrong size!
fi
# end of './GNUmake.config'
fi
if test -f './GNUmakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./GNUmakefile'\"
else
echo shar: Extracting \"'./GNUmakefile'\" \(621 characters\)
sed "s/^X//" >'./GNUmakefile' <<'END_OF_FILE'
X#
X# GNU makefile for ethernet library
X#
X
Xinclude GNUmake.config
X
XOPTG := -O $(OPTG)
XOPT := -O
XDEFINES =
X
X# This doesn't do anything - it just hands it off to the subdirectory
X
X.PHONY: all install lint noise listing clean cleanlists realclean
X
Xall install ethertest ctp: $(SYSTEM)
X	$(MAKE) -C $(SYSTEM) -f ../GNUmake.mk $@
X
Xlint noise listing:
X	$(MAKE) -C src -f ../GNUmake.mk $@
X
Xclean: $(SYSTEM)
X	$(MAKE) -C $(SYSTEM) -f ../GNUmake.mk $@
X
Xrealclean: $(SYSTEM)
X	$(MAKE) -C $(SYSTEM) -f ../GNUmake.mk $@
X	$(MAKE) -C src -f ../GNUmake.mk $@
X
X$(SYSTEM):
X	mkdir $(SYSTEM)
X
X.DEFAULT:
X	$(MAKE) -C $(SYSTEM) -f ../GNUmake.mk $@
END_OF_FILE
if test 621 -ne `wc -c <'./GNUmakefile'`; then
    echo shar: \"'./GNUmakefile'\" unpacked with wrong size!
fi
# end of './GNUmakefile'
fi
if test -f './ReadMe' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./ReadMe'\"
else
echo shar: Extracting \"'./ReadMe'\" \(644 characters\)
sed "s/^X//" >'./ReadMe' <<'END_OF_FILE'
X
XThis is the source tree for the ethernet interface library.
X
XGNUmakefile
X
X	is the master makefile for the ethernet interface library.
X
XGNUmake.mk
X
X	is used as a common makefile for the architecture-specific
X	subdirectories.
X
Xether.3n
X
X	manual page describing the library routines
X
XInstructions
X
X	are instructions for building this library.
X
XSunBugs
X
X	describes several bugs in the Sun 4.0 NIT interface
X
XThere are the following subdirectories
X
X	src		contains the sources
X	tests		contains the source for test programs
X	enet		contains sources for Stanford enetfilter
X
X	sun3		have object files for various architectures
X	sun3-os4
X	sun4-os4
X	etc.
END_OF_FILE
if test 644 -ne `wc -c <'./ReadMe'`; then
    echo shar: \"'./ReadMe'\" unpacked with wrong size!
fi
# end of './ReadMe'
fi
if test ! -d './src' ; then
    echo shar: Creating directory \"'./src'\"
    mkdir './src'
fi
if test -f './src/ReadMe' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/ReadMe'\"
else
echo shar: Extracting \"'./src/ReadMe'\" \(1021 characters\)
sed "s/^X//" >'./src/ReadMe' <<'END_OF_FILE'
X
XThis is the source subtree for the ethernet interface library.
X
XMakefile
X
X	is a no-frills makefile for the ethernet interface library, so that it
X	can be distributed separately, and used with any make.  If you have GNU
X	make, you should be using the GNUmakefile in the parent directory.
X
Xether.h
X
X	is the external interface header file for installation in /usr/include.
X
Xlibether.h
X
X	is the internal header file, for use by the library only.
X
Xetherblock.c
Xetherints.c
X
X	are generic, and should work on any system with Berkeley sockets.
X
Xetherread.c
X
X	is somewhat generic, and works on SunOS 4.x and BSD+enetfilter systems.
X
Xnitaddr.c
X
X	has generic NIT code, and should work on any system with NIT.
X
Xnit4open.c
X
X	has streams-based NIT code, and works only on SunOS 4.x systems.
X
Xnit3open.c
X
X	has socket-based NIT code, and works only on SunOS 3.x systems.
X
Xdliopen.c
X
X	has Ultrix DLI code, and works only on Ultrix systems.
X
Xenetaddr.c
Xenetopen.c
X
X	have Stanford enetfilter code, and work only on BSD+enetfilter systems.
END_OF_FILE
if test 1021 -ne `wc -c <'./src/ReadMe'`; then
    echo shar: \"'./src/ReadMe'\" unpacked with wrong size!
fi
# end of './src/ReadMe'
fi
if test -f './src/dliaddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/dliaddr.c'\"
else
echo shar: Extracting \"'./src/dliaddr.c'\" \(1468 characters\)
sed "s/^X//" >'./src/dliaddr.c' <<'END_OF_FILE'
X/* $Id: dliaddr.c,v 2.0 89/10/20 19:01:26 dupuy Exp $ */
X
X#include <sys/param.h>			/* NOFILE */
X#include <sys/ioctl.h>			/* ioctl */
X#include <sys/socket.h>			/* sockaddr_dl (sockaddr) */
X
X#include <net/if.h>			/* ifdevea */
X#include <netinet/in.h>			/* (ether_header) (in_addr) */
X#include <netinet/if_ether.h>		/* sockaddr_dl (ether_header)  */
X#include <netdnet/dli_var.h>		/* sockaddr_dl */
X
X#include "libether.h"
X
Xextern struct sockaddr_dl _ether_sockaddrs[NOFILE];
X
X#define sad (_ether_sockaddrs[fd])
X
X
Xstatic void
Xdevid_to_name (name, devid)
Xchar *name;
Xstruct dli_devid *devid;
X{
X    register int i;
X
X    for (i = 0; devid->dli_devname[i]; i++)
X	name[i] = devid->dli_devname[i];
X
X    name[i++] = '0' + devid->dli_devnumber;
X
X    name[i] = '\0';
X}
X
X
X/*
X * Returns the local ethernet address for the ethernet interface on the file
X * descriptor fd.  The result is stored in the structure given by address; if
X * none is given, malloc is used to allocate space.
X */
X
Xether_addr *
Xether_address (fd, address)
Xint fd;
Xether_addr *address;
X{
X    struct ifdevea ifd;
X
X    devid_to_name (ifd.ifr_name, &sad.dli_device);
X
X    if (ioctl (fd, SIOCRPHYSADDR, (char *) &ifd) < 0)
X    {
X#ifdef DEBUG
X	perror ("ether_address: ioctl SIOCRPHYSADDR");
X#endif
X	return (0);
X    }
X
X    if (address == 0)
X	address = (ether_addr *) malloc (sizeof (ether_addr));
X
X    if (address != 0)
X	bcopy ((char *) ifd.current_pa, (char *) address, sizeof (ether_addr));
X
X    return (address);
X}
END_OF_FILE
if test 1468 -ne `wc -c <'./src/dliaddr.c'`; then
    echo shar: \"'./src/dliaddr.c'\" unpacked with wrong size!
fi
# end of './src/dliaddr.c'
fi
if test -f './src/dliintaddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/dliintaddr.c'\"
else
echo shar: Extracting \"'./src/dliintaddr.c'\" \(821 characters\)
sed "s/^X//" >'./src/dliintaddr.c' <<'END_OF_FILE'
X/* $Id: dliintaddr.c,v 2.1 89/10/23 15:41:58 dupuy Exp $ */
X
X#include <errno.h>
X
Xextern int errno;
X
X#include "libether.h"
X
X/*
X * Returns the local ethernet address for the ethernet interface.  The result
X * is stored in the structure given by address; if none is given, malloc is
X * used to allocate space.
X */
X
Xether_addr *
Xether_intfaddr (intf, address)
Xchar *intf;
Xether_addr *address;
X{
X    int fd;
X    unsigned short proto = 0xffff;
X    int saved_errno;
X
X    do
X	if ((fd = ether_open (intf, proto--, (ether_addr *) 0)) < 0)
X	{
X	    if (errno == EADDRINUSE)
X		continue;
X	    return (0);
X	}				/* constant argument to NOT ??? */
X    while (fd < 0 && proto >= ETHER_MINTYPE);
X
X    address = ether_address (fd, address);
X
X    saved_errno = errno;
X    (void) close (fd);
X    errno = saved_errno;
X
X    return (address);
X}
END_OF_FILE
if test 821 -ne `wc -c <'./src/dliintaddr.c'`; then
    echo shar: \"'./src/dliintaddr.c'\" unpacked with wrong size!
fi
# end of './src/dliintaddr.c'
fi
if test -f './src/dliread.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/dliread.c'\"
else
echo shar: Extracting \"'./src/dliread.c'\" \(1891 characters\)
sed "s/^X//" >'./src/dliread.c' <<'END_OF_FILE'
X/* $Id: dliread.c,v 2.1 89/10/23 15:42:04 dupuy Exp $ */
X
X#include <sys/param.h>			/* NOFILE */
X#include <sys/socket.h>			/* sockaddr_dl (sockaddr) */
X
X#include <net/if.h>			/* ifdevea */
X#include <netinet/in.h>			/* (ether_header) (in_addr) */
X#include <netinet/if_ether.h>		/* sockaddr_dl (ether_header) */
X#include <netdnet/dli_var.h>		/* sockaddr_dl */
X
X#include <errno.h>			/* EWOULDBLOCK */
X
X#include "libether.h"
X
Xextern ether_addr _ether_multi_addrs[NOFILE];
X
X/*
X * Reads and returns a single packet, filling in all fields.  If pktbuf is
X * NULL, a buffer is allocated for it.	If pktbuf is not NULL, the function
X * assumes that pktbuf is large enough to hold pktlen bytes.  Has to do
X * address checking, since we are operating in DLI_EXCLUSIVE mode.
X */
X
Xint
Xether_read (fd, packet)
Xint fd;
Xether_packet *packet;
X{
X    struct sockaddr_dl from;
X    int alen;
X    int count;
X    char *dest;
X
X    if (packet->pktbuf == 0)
X    {
X	packet->pktlen = ETHER_MAX;
X	if ((packet->pktbuf = (char *) malloc ((unsigned) ETHER_MAX)) == 0)
X	    return (-1);
X    }
X
X    from.dli_family = AF_DLI;
X    alen = sizeof (from);
X
X    do					/* ignore bogus multicast packets */
X    {
X	if ((count = recvfrom (fd, packet->pktbuf, (int) packet->pktlen, 0,
X			       (struct sockaddr *) &from, &alen)) < 0)
X	{
X	    if (errno == EWOULDBLOCK)
X		errno = EAGAIN;
X	    return (-1);
X	}
X
X	dest = (char *) from.choose_addr.dli_eaddr.dli_dest;
X    }
X    while (address_check (dest));	/* constant argument to NOT ??? */
X
X    bcopy (dest, (char *) &packet->dest, sizeof (ether_addr));
X    bcopy ((char *) from.choose_addr.dli_eaddr.dli_target,
X	   (char *) &packet->src, sizeof (ether_addr));
X    packet->type[0] = (from.choose_addr.dli_eaddr.dli_protype & 0xff00) >> 8;
X    packet->type[1] = from.choose_addr.dli_eaddr.dli_protype & 0xff;
X
X    if (packet->pktlen > count)
X	packet->pktlen = count;
X
X    return (count);
X}
END_OF_FILE
if test 1891 -ne `wc -c <'./src/dliread.c'`; then
    echo shar: \"'./src/dliread.c'\" unpacked with wrong size!
fi
# end of './src/dliread.c'
fi
if test -f './src/dlireadv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/dlireadv.c'\"
else
echo shar: Extracting \"'./src/dlireadv.c'\" \(1664 characters\)
sed "s/^X//" >'./src/dlireadv.c' <<'END_OF_FILE'
X/* $Id: dlireadv.c,v 2.1 89/10/23 15:42:06 dupuy Exp $ */
X
X#include <sys/param.h>			/* NOFILE */
X#include <sys/socket.h>			/* sockaddr_dl (sockaddr) */
X#include <sys/uio.h>			/* iovec */
X
X#include <net/if.h>			/* ifdevea */
X#include <netinet/in.h>			/* (ether_header) (in_addr) */
X#include <netinet/if_ether.h>		/* sockaddr_dl (ether_header) */
X#include <netdnet/dli_var.h>		/* sockaddr_dl */
X
X#include <errno.h>			/* EWOULDBLOCK */
X
X#include "libether.h"
X
Xextern ether_addr _ether_multi_addrs[NOFILE];
X
X
X/*
X * Reads and returns a single packet, filling in all fields.  Has to do
X * address checking, since we are operating in DLI_EXCLUSIVE mode.
X */
X
Xint
Xether_readv (fd, packet)
Xint fd;
Xether_vec *packet;
X{
X    struct sockaddr_dl from;
X    struct msghdr msg;
X    int count;
X    char *dest;
X
X    from.dli_family = AF_DLI;
X    msg.msg_iov = packet->iov;
X    msg.msg_iovlen = packet->iovcnt;
X    msg.msg_name = (caddr_t) &from;
X    msg.msg_namelen = sizeof (from);
X    msg.msg_accrights = 0;
X    msg.msg_accrightslen = 0;
X
X    do					/* ignore bogus multicast packets */
X    {
X	if ((count = recvmsg (fd, &msg, 0)) < 0)
X	{
X	    if (errno == EWOULDBLOCK)
X		errno = EAGAIN;
X	    return (-1);
X	}
X
X	dest = (char *) from.choose_addr.dli_eaddr.dli_dest;
X    }
X    while (address_check (dest));	/* constant argument to NOT ??? */
X
X    bcopy (dest, (char *) &packet->dest, sizeof (ether_addr));
X    bcopy ((char *) from.choose_addr.dli_eaddr.dli_target,
X	   (char *) &packet->src, sizeof (ether_addr));
X    packet->type[0] = (from.choose_addr.dli_eaddr.dli_protype & 0xff00) >> 8;
X    packet->type[1] = from.choose_addr.dli_eaddr.dli_protype & 0xff;
X
X    return (count);
X}
END_OF_FILE
if test 1664 -ne `wc -c <'./src/dlireadv.c'`; then
    echo shar: \"'./src/dlireadv.c'\" unpacked with wrong size!
fi
# end of './src/dlireadv.c'
fi
if test -f './src/dliself.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/dliself.c'\"
else
echo shar: Extracting \"'./src/dliself.c'\" \(1415 characters\)
sed "s/^X//" >'./src/dliself.c' <<'END_OF_FILE'
X/* $Id: dliself.c,v 2.0 89/10/20 19:01:55 dupuy Exp $ */
X
X#include <sys/param.h>			/* NOFILE */
X#include <sys/socket.h>			/* sockaddr_dl (sockaddr) */
X
X#include <net/if.h>			/* (ether_header) (ifnet) */
X#include <netinet/in.h>			/* (ether_header) (in_addr) */
X#include <netinet/if_ether.h>		/* sockaddr_dl (ether_header) */
X#include <netdnet/dli_var.h>		/* sockaddr_dl */
X
Xextern struct sockaddr_dl _ether_sockaddrs[NOFILE];
X
X#define sad (_ether_sockaddrs[fd])
X
X/*
X * Most, but not all, VAX interfaces, loopback packets.	 The Ultrix drivers
X * for the rest try (with varying degrees of success) to compensate for that
X * as far as broadcast packets go.  The ec (3com) driver does it only for IP
X * packets, and does not support multicast, and seems to be unsupported by
X * DEC.
X */
X
Xstatic char *softloops[] = {"ec", "qe", "se"};
X
Xint
Xether_send_self (fd)
Xint fd;
X{
X    unsigned char *devname = sad.dli_device.dli_devname;
X    int i;
X
X    for (i = 0; i < sizeof (softloops) / sizeof (softloops[0]); i++)
X	if (!strcmp ((char *) devname, softloops[i]))
X	    return (0);
X
X    return (1);				/* default to true */
X}
X
Xint
Xether_mcast_self (fd)
Xint fd;
X{
X    return (ether_send_self (fd));
X}
X
Xint
Xether_bcast_self (fd)
Xint fd;
X{
X    unsigned char *devname = sad.dli_device.dli_devname;
X
X    if (!strcmp ((char *) devname, "ec"))
X	return (0);			/* the ec driver is broken... */
X
X    return (1);				/* default to true */
X}
END_OF_FILE
if test 1415 -ne `wc -c <'./src/dliself.c'`; then
    echo shar: \"'./src/dliself.c'\" unpacked with wrong size!
fi
# end of './src/dliself.c'
fi
if test -f './src/dliwrite.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/dliwrite.c'\"
else
echo shar: Extracting \"'./src/dliwrite.c'\" \(971 characters\)
sed "s/^X//" >'./src/dliwrite.c' <<'END_OF_FILE'
X/* $Id: dliwrite.c,v 2.1 89/10/23 15:42:09 dupuy Exp $ */
X
X#include <sys/param.h>			/* NOFILE */
X#include <sys/socket.h>			/* sockaddr_dl (sockaddr) */
X
X#include <net/if.h>			/* ifdevea */
X#include <netinet/in.h>			/* (ether_header) (in_addr) */
X#include <netinet/if_ether.h>		/* sockaddr_dl (ether_header) */
X#include <netdnet/dli_var.h>		/* sockaddr_dl */
X
X#include <errno.h>			/* EWOULDBLOCK */
X
X#include "libether.h"
X
Xextern struct sockaddr_dl _ether_sockaddrs[NOFILE];
X
X#define sad (_ether_sockaddrs[fd])
X
X/*
X * Writes a single packet, filling src and type fields.
X */
X
Xint
Xether_write (fd, packet)
Xint fd;
Xether_packet *packet;
X{
X    int result;
X
X    bcopy ((char *) &packet->dest,
X	   (char *) sad.choose_addr.dli_eaddr.dli_target, DLI_EADDRSIZE);
X
X    result = sendto (fd, packet->pktbuf, (int) packet->pktlen, 0,
X		     (struct sockaddr *) &sad, sizeof (struct sockaddr_dl));
X
X    if (result < 0 && errno == EWOULDBLOCK)
X	errno = EAGAIN;
X
X    return (result);
X}
END_OF_FILE
if test 971 -ne `wc -c <'./src/dliwrite.c'`; then
    echo shar: \"'./src/dliwrite.c'\" unpacked with wrong size!
fi
# end of './src/dliwrite.c'
fi
if test -f './src/dliwritev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/dliwritev.c'\"
else
echo shar: Extracting \"'./src/dliwritev.c'\" \(1132 characters\)
sed "s/^X//" >'./src/dliwritev.c' <<'END_OF_FILE'
X/* $Id: dliwritev.c,v 2.1 89/10/23 15:42:10 dupuy Exp $ */
X
X#include <sys/param.h>			/* NOFILE */
X#include <sys/socket.h>			/* sockaddr_dl (sockaddr) */
X#include <sys/uio.h>			/* iovec */
X
X#include <net/if.h>			/* ifdevea */
X#include <netinet/in.h>			/* (ether_header) (in_addr) */
X#include <netinet/if_ether.h>		/* sockaddr_dl (ether_header) */
X#include <netdnet/dli_var.h>		/* sockaddr_dl */
X
X#include <errno.h>			/* EWOULDBLOCK */
X
X#include "libether.h"
X
Xextern struct sockaddr_dl _ether_sockaddrs[NOFILE];
X
X#define sad (_ether_sockaddrs[fd])
X
X/*
X * Writes a single packet, filling src and type fields.
X */
X
Xint
Xether_writev (fd, packet)
Xint fd;
Xether_vec *packet;
X{
X    struct msghdr msg;
X    int result;
X
X    bcopy ((char *) &packet->dest,
X	   (char *) sad.choose_addr.dli_eaddr.dli_target, DLI_EADDRSIZE);
X
X    msg.msg_iov = packet->iov;
X    msg.msg_iovlen = packet->iovcnt;
X    msg.msg_name = (caddr_t) &sad;
X    msg.msg_namelen = sizeof (sad);
X    msg.msg_accrights = 0;
X    msg.msg_accrightslen = 0;
X
X    result = sendmsg (fd, &msg, 0);
X
X    if (result < 0 && errno == EWOULDBLOCK)
X	errno = EAGAIN;
X
X    return (result);
X}
END_OF_FILE
if test 1132 -ne `wc -c <'./src/dliwritev.c'`; then
    echo shar: \"'./src/dliwritev.c'\" unpacked with wrong size!
fi
# end of './src/dliwritev.c'
fi
if test -f './src/enetaddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/enetaddr.c'\"
else
echo shar: Extracting \"'./src/enetaddr.c'\" \(1415 characters\)
sed "s/^X//" >'./src/enetaddr.c' <<'END_OF_FILE'
X/* $Id: enetaddr.c,v 2.0 89/10/20 19:01:58 dupuy Exp $ */
X
X#include <sys/types.h>			/* FD_ISSET */
X#include <sys/ioctl.h>			/* ioctl */
X
X#include <net/enet.h>			/* endevp */
X
X#include "libether.h"
X
Xstatic fd_set addrcachevalid;
X
Xstatic ether_addr ifaddrs[FD_SETSIZE];
X
X#define ifaddr (ifaddrs[fd])
X
X/*
X * Returns the local ethernet address for the ethernet interface on the file
X * descriptor fd.  The result is stored in the structure given by address; if
X * none is given, malloc is used to allocate space.  We cache results here
X * because this function is called every time we send a packet.
X */
X
Xether_addr *
Xether_address (fd, address)
Xint fd;
Xether_addr *address;
X{
X    if (!FD_ISSET (fd, &addrcachevalid))
X    {
X	struct endevp edev;
X
X	if (ioctl (fd, EIOCDEVP, (char *) &edev) < 0)
X	{
X#ifdef DEBUG
X	    perror ("ether_address: ioctl EIOCDEVP");
X#endif
X	    return (0);
X	}
X
X	bcopy ((char *) edev.end_addr, (char *) &ifaddr, sizeof (ether_addr));
X
X	FD_SET (fd, &addrcachevalid);
X    }
X
X
X    if (address == 0)
X	address = (ether_addr *) malloc (sizeof (ether_addr));
X
X    if (address != 0)
X	bcopy ((char *) &ifaddr, (char *) address, sizeof (ether_addr));
X
X    return (address);
X}
X
X/*
X * This function is called by ether_open to invalidate the local address
X * cache, since the file descriptor may be attached to a different interface.
X */
X
Xvoid
X_ether_newaddr (fd)
Xint fd;
X{
X    FD_CLR (fd, &addrcachevalid);
X}
END_OF_FILE
if test 1415 -ne `wc -c <'./src/enetaddr.c'`; then
    echo shar: \"'./src/enetaddr.c'\" unpacked with wrong size!
fi
# end of './src/enetaddr.c'
fi
if test -f './src/enetblock.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/enetblock.c'\"
else
echo shar: Extracting \"'./src/enetblock.c'\" \(980 characters\)
sed "s/^X//" >'./src/enetblock.c' <<'END_OF_FILE'
X/* $Id: enetblock.c,v 2.0 89/10/20 19:02:00 dupuy Exp $ */
X
X#include <sys/types.h>			/* eniocb (u_char) */
X#include <net/enet.h>			/* eniocb */
X
X#define ERR (-1)
X
X/*
X * If state is false (0), set ethernet file descriptor fd to be non-blocking,
X * else set fd to be blocking. If there is an error, ether_blocking() returns
X * (-1) and the appropriate value is left in errno.  Normal return status
X * zero.
X *
X * We _ought_ to be able to use fcntl like SunOS and Ultrix, but since the enet
X * special device doesn't support the FIONBIO ioctl, we can't.	This is a bug
X * in the enet device driver which should be fixed.  Furthermore, this only
X * prevents blocking on reads (the most common case, admittedly).  Writes to
X * ethernet devices can still block waiting for queue resources.
X */
X
Xint
Xether_blocking (fd, state)
Xint fd;
Xint state;
X{
X    struct eniocb eni;
X
X    if (state)
X	eni.en_rtout = 0;
X    else
X	eni.en_rtout = -1;
X
X    return (ioctl (fd, EIOCSETP, (char *) &eni));
X}
END_OF_FILE
if test 980 -ne `wc -c <'./src/enetblock.c'`; then
    echo shar: \"'./src/enetblock.c'\" unpacked with wrong size!
fi
# end of './src/enetblock.c'
fi
if test -f './src/enetintaddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/enetintaddr.c'\"
else
echo shar: Extracting \"'./src/enetintaddr.c'\" \(1076 characters\)
sed "s/^X//" >'./src/enetintaddr.c' <<'END_OF_FILE'
X/* $Id: enetintaddr.c,v 2.0 89/10/20 19:02:02 dupuy Exp $ */
X
X#include <strings.h>			/* strcpy */
X#include <sys/types.h>			/* (sockaddr) (u_short) */
X#include <sys/socket.h>			/* IFNAMSIZ (sockaddr) */
X#include <sys/file.h>			/* O_RDWR */
X#include <net/if.h>			/* IFNAMSIZ */
X
Xextern int errno;
X
X#include "libether.h"
X
X#ifndef ENET_DEVDIR
X#define ENET_DEVDIR "/dev/enet/"
X#endif
X
X/*
X * Returns the local ethernet address for an ethernet interface.  The result
X * is stored in the structure given by address; if none is given, malloc is
X * used to allocate space.
X */
X
Xether_addr *
Xether_intfaddr (intf, address)
Xchar *intf;
Xether_addr *address;
X{
X    char pathname[sizeof (ENET_DEVDIR) + IFNAMSIZ];
X    int fd;
X    int saved_errno;
X
X    (void) strcpy (pathname, ENET_DEVDIR);
X    (void) strncat (pathname, intf, IFNAMSIZ);
X
X    if ((fd = open (pathname, O_RDWR)) < 0)
X    {
X#ifdef DEBUG
X	perror (pathname);
X#endif
X	return (0);
X    }
X
X    address = ether_address (fd, address);
X
X    saved_errno = errno;
X    (void) close (fd);
X    errno = saved_errno;
X
X    return (address);
X}
END_OF_FILE
if test 1076 -ne `wc -c <'./src/enetintaddr.c'`; then
    echo shar: \"'./src/enetintaddr.c'\" unpacked with wrong size!
fi
# end of './src/enetintaddr.c'
fi
if test -f './src/enetself.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/enetself.c'\"
else
echo shar: Extracting \"'./src/enetself.c'\" \(601 characters\)
sed "s/^X//" >'./src/enetself.c' <<'END_OF_FILE'
X/* $Id: enetself.c,v 2.0 89/10/20 19:02:05 dupuy Exp $ */
X
X/*
X * Most, but not all, VAX interfaces, loopback packets.	 The enetfilter
X * drivers for the ec (3com) interface loops back packets in software, except
X * for multicast packets.  Since the enetfilter currently has no way to
X * receive multicast packets, that makes little difference.
X */
X
X/* ARGSUSED */
X
Xint
Xether_send_self (fd)
Xint fd;
X{
X    return (1);
X}
X
X/* ARGSUSED */
X
Xint
Xether_mcast_self (fd)
Xint fd;
X{
X    return (0);				/* can't receive multicast packets */
X}
X
X/* ARGSUSED */
X
Xint
Xether_bcast_self (fd)
Xint fd;
X{
X    return (1);
X}
END_OF_FILE
if test 601 -ne `wc -c <'./src/enetself.c'`; then
    echo shar: \"'./src/enetself.c'\" unpacked with wrong size!
fi
# end of './src/enetself.c'
fi
if test -f './src/enetwrite.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/enetwrite.c'\"
else
echo shar: Extracting \"'./src/enetwrite.c'\" \(1012 characters\)
sed "s/^X//" >'./src/enetwrite.c' <<'END_OF_FILE'
X/* $Id: enetwrite.c,v 2.1 89/10/24 17:53:05 dupuy Exp $ */
X
X#include <sys/types.h>			/* iovec (caddr_t) */
X#include <sys/uio.h>			/* iovec */
X
X#include "libether.h"
X
Xextern unsigned _ether_types[FD_SETSIZE];
X
X#define ether_type (_ether_types[fd])
X
X#define HEADER	0
X#define DATA	1
X#define MAXIOV	2
X
X/*
X * Writes a single packet, filling src and type fields.	 We have to fill in
X * the src field in user space, since the enetfilter doesn't do it for us, and
X * at least some VAX interface devices don't do it either.
X */
X
Xint
Xether_write (fd, packet)
Xint fd;
Xether_packet *packet;
X{
X    struct iovec iov[MAXIOV];
X
X    iov[HEADER].iov_len = ETHER_PKT;
X    iov[HEADER].iov_base = (char *) packet;
X
X    iov[DATA].iov_len = packet->pktlen;
X    iov[DATA].iov_base = packet->pktbuf;
X
X    if (ether_type != ETHER_ALLTYPES)
X    {
X	packet->type[0] = (ether_type >> 8) & 0xff;
X	packet->type[1] = ether_type & 0xff;
X    }
X
X    (void) ether_address (fd, (ether_addr *) &packet->src);
X
X    return (writev (fd, iov, MAXIOV));
X}
END_OF_FILE
if test 1012 -ne `wc -c <'./src/enetwrite.c'`; then
    echo shar: \"'./src/enetwrite.c'\" unpacked with wrong size!
fi
# end of './src/enetwrite.c'
fi
if test -f './src/enetwritev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/enetwritev.c'\"
else
echo shar: Extracting \"'./src/enetwritev.c'\" \(1313 characters\)
sed "s/^X//" >'./src/enetwritev.c' <<'END_OF_FILE'
X/* $Id: enetwritev.c,v 2.2 89/10/24 17:53:10 dupuy Exp $ */
X
X#include <sys/types.h>			/* iovec (caddr_t) */
X#include <sys/uio.h>			/* iovec */
X
X#include "libether.h"
X
X#ifdef __GNUC__
X#define alloca __builtin_alloca
X#else
X#ifdef lint
Xextern double *dalloca ();
X#define alloca dalloca
X#else
X#ifdef sparc
X#include <alloca.h>
X#endif
Xextern char *alloca ();
X#endif
X#endif
X
Xextern unsigned _ether_types[FD_SETSIZE];
X
X#define ether_type (_ether_types[fd])
X
X#define HEADER	0
X#define USER	1
X
X/*
X * Writes a single packet, filling src and type fields.	 We have to fill in
X * the src field in user space, since the enetfilter doesn't do it for us, and
X * at least some VAX interface devices don't do it either.
X */
X
Xint
Xether_writev (fd, packet)
Xint fd;
Xether_vec *packet;
X{
X    int count = 1 + packet->iovcnt;
X    struct iovec *iov =
X	(struct iovec *) alloca (sizeof (struct iovec) * count);
X
X    iov[HEADER].iov_len = ETHER_PKT;
X    iov[HEADER].iov_base = (char *) packet;
X
X    (void) bcopy ((char *) packet->iov, (char *) &iov[USER],
X		  (int) packet->iovcnt * sizeof (struct iovec));
X
X    if (ether_type != ETHER_ALLTYPES)
X    {
X	packet->type[0] = (ether_type >> 8) & 0xff;
X	packet->type[1] = ether_type & 0xff;
X    }
X
X    (void) ether_address (fd, (ether_addr *) &packet->src);
X
X    return (writev (fd, iov, count));
X}
END_OF_FILE
if test 1313 -ne `wc -c <'./src/enetwritev.c'`; then
    echo shar: \"'./src/enetwritev.c'\" unpacked with wrong size!
fi
# end of './src/enetwritev.c'
fi
if test -f './src/ethera2e.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/ethera2e.c'\"
else
echo shar: Extracting \"'./src/ethera2e.c'\" \(995 characters\)
sed "s/^X//" >'./src/ethera2e.c' <<'END_OF_FILE'
X/* $Id: ethera2e.c,v 2.1 89/10/23 15:42:22 dupuy Exp $ */
X
X#include <stdio.h>			/* sscanf */
X
X#include "libether.h"
X
X#define EBYTES 6
X
Xether_addr *
Xether_a2e (estring, addr)
Xchar *estring;
Xether_addr *addr;
X{
X    unsigned bytes[EBYTES];
X    int allocated = 0;
X    int i;
X
X    if (addr == NULL)
X    {
X	addr = (ether_addr *) malloc (sizeof (ether_addr));
X	allocated++;
X    }
X
X    if (addr != NULL)
X	if (sscanf (estring, " %2x:%2x:%2x:%2x:%2x:%2x", &bytes[0], &bytes[1],
X		    &bytes[2], &bytes[3], &bytes[4], &bytes[5])
X	    == EBYTES ||
X	    sscanf (estring, " %2x-%2x-%2x-%2x-%2x-%2x", &bytes[0], &bytes[1],
X		    &bytes[2], &bytes[3], &bytes[4], &bytes[5])
X	    == EBYTES)
X	{
X	    for (i = 0; i < EBYTES; i++)
X		addr->bytes[i] = bytes[i];
X	}
X	else
X	{
X	    if (allocated)
X		(void) free ((char *) addr);
X	    addr = NULL;
X	}
X
X    return (addr);
X}
X
X#ifndef ETHERDB
X
Xether_addr *
Xether_aton (estring)
Xchar *estring;
X{
X    static ether_addr addr;
X
X    return (ether_a2e (estring, &addr));
X}
X
X#endif
END_OF_FILE
if test 995 -ne `wc -c <'./src/ethera2e.c'`; then
    echo shar: \"'./src/ethera2e.c'\" unpacked with wrong size!
fi
# end of './src/ethera2e.c'
fi
if test -f './src/etheraddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/etheraddr.c'\"
else
echo shar: Extracting \"'./src/etheraddr.c'\" \(755 characters\)
sed "s/^X//" >'./src/etheraddr.c' <<'END_OF_FILE'
X/* $Id: etheraddr.c,v 2.1 89/10/23 15:44:44 dupuy Exp $ */
X
X/*
X * Static initialization of ethernet broadcast address.	 We do it in a separate
X * file so that it can be compiled with -R (read-only), but more importatntly,
X * so that we can get around the restriction on initializing unions if needed.
X */
X
X#ifdef __STDC__
X
X#include "ether.h"
X
Xether_addr ether_bcast_addr = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
X
X#else
X
X#ifdef lint
X
X#include "ether.h"
X
Xether_addr ether_bcast_addr;		/* a little white lie */
X
X#else
X
X#define __ETHER_BCAST_ADDR__		/* avoid conflict with ether.h */
X
X#include "ether.h"
X
Xstruct ether_addr
X{
X    unsigned short shorts[3];		/* must have short alignment */
X}
Xether_bcast_addr =  {{ 0xffff, 0xffff, 0xffff }};
X
X#endif
X
X#endif
END_OF_FILE
if test 755 -ne `wc -c <'./src/etheraddr.c'`; then
    echo shar: \"'./src/etheraddr.c'\" unpacked with wrong size!
fi
# end of './src/etheraddr.c'
fi
if test -f './src/etherblock.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/etherblock.c'\"
else
echo shar: Extracting \"'./src/etherblock.c'\" \(890 characters\)
sed "s/^X//" >'./src/etherblock.c' <<'END_OF_FILE'
X/* $Id: etherblock.c,v 2.1 89/10/23 15:42:26 dupuy Exp $ */
X
X#include <sys/file.h>			/* FNBIO/FNDELAY */
X
X#ifdef __STDC__
Xextern int fcntl (int f, int c, int a);
X#else
Xextern int fcntl ();
X#endif
X
X#ifdef FNBIO
X#define FNOBLOCK FNBIO
X#else
X#define FNOBLOCK FNDELAY
X#endif
X
X#define ERR (-1)
X
X/*
X * If state is false (0), set ethernet file descriptor fd to be non-blocking,
X * else set fd to be blocking. If there is an error, ether_blocking() returns
X * (-1) and the appropriate value is left in errno.  Normal return status
X * zero.
X */
X
Xint
Xether_blocking (fd, state)
Xint fd;
Xint state;
X{
X    int flags;
X
X    if ((flags = fcntl (fd, F_GETFL, -1)) < 0)
X	return (ERR);
X
X    if (state)
X	if (flags & FNOBLOCK)
X	    state = fcntl (fd, F_SETFL, flags & ~FNOBLOCK);
X	else
X	    state = 0;
X    else if ((flags & FNOBLOCK) == 0)
X	state = fcntl (fd, F_SETFL, flags | FNOBLOCK);
X
X    return (state);
X}
END_OF_FILE
if test 890 -ne `wc -c <'./src/etherblock.c'`; then
    echo shar: \"'./src/etherblock.c'\" unpacked with wrong size!
fi
# end of './src/etherblock.c'
fi
if test -f './src/ethere2a.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/ethere2a.c'\"
else
echo shar: Extracting \"'./src/ethere2a.c'\" \(630 characters\)
sed "s/^X//" >'./src/ethere2a.c' <<'END_OF_FILE'
X/* $Id: ethere2a.c,v 2.1 89/10/23 15:42:28 dupuy Exp $ */
X
X#include <stdio.h>
X
X#include "libether.h"
X
Xchar *
Xether_e2a (addr, estring)
Xether_addr *addr;
Xchar *estring;
X{
X#ifdef lint
X    char *sprintf ();
X#endif
X    if (estring == NULL)
X	estring = (char *) malloc (ETHERSTRLEN);
X
X    if (estring != NULL)
X	(void) sprintf (estring, "%x:%x:%x:%x:%x:%x",
X			addr->bytes[0], addr->bytes[1], addr->bytes[2],
X			addr->bytes[3], addr->bytes[4], addr->bytes[5]);
X    return (estring);
X}
X
X#ifndef ETHERDB
X
Xchar *
Xether_ntoa (addr)
Xether_addr *addr;
X{
X    static char estring[ETHERSTRLEN];
X
X    return (ether_e2a (addr, estring));
X}
X
X#endif
END_OF_FILE
if test 630 -ne `wc -c <'./src/ethere2a.c'`; then
    echo shar: \"'./src/ethere2a.c'\" unpacked with wrong size!
fi
# end of './src/ethere2a.c'
fi
if test -f './src/etherlocal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/etherlocal.c'\"
else
echo shar: Extracting \"'./src/etherlocal.c'\" \(1143 characters\)
sed "s/^X//" >'./src/etherlocal.c' <<'END_OF_FILE'
X/* $Id: etherlocal.c,v 2.1 89/10/23 15:42:38 dupuy Exp $ */
X
X#include <sys/types.h>			/* (u_char) */
X#include <sys/socket.h>			/* sockaddr_in (sockaddr) */
X#include <net/if.h>			/* ifconf */
X#include <netinet/in.h>			/* sockaddr_in */
X#include <errno.h>
X
Xextern int errno;
X
X#include "libether.h"
X
Xextern short _ether_ifindex[MAXNUMIF];	/* from ether_interfaces() */
Xextern struct ifconf _ether_ifconf;	/* from ether_interfaces() */
X
X
Xint
X_ether_localif (addr, ipaddr)
Xether_addr *addr;
Xstruct in_addr *ipaddr;
X{
X    char **intfs;
X    int i;
X
X    if ((intfs = ether_interfaces ()) == 0)
X	return (0);
X
X    for (i = 0; *intfs; intfs++, i++)
X    {
X	ether_addr eaddr;
X
X	if (_ether_ifindex[i] < 0)
X	    continue;			/* not an AF_INET interface */
X
X	if (ether_intfaddr (*intfs, &eaddr) == 0)
X	    return (0);
X
X	if (ether_cmp (addr, &eaddr) == 0)
X	{
X	    struct sockaddr_in *inaddr;
X
X	    inaddr = (struct sockaddr_in *)
X		&_ether_ifconf.ifc_req[_ether_ifindex[i]].ifr_addr;
X
X	    (void) bcopy ((char *) &inaddr->sin_addr, (char *) ipaddr,
X			  sizeof (*ipaddr));
X	    return (1);
X	}
X    }
X
X    return (0);				/* doesn't match any local interface */
X}
END_OF_FILE
if test 1143 -ne `wc -c <'./src/etherlocal.c'`; then
    echo shar: \"'./src/etherlocal.c'\" unpacked with wrong size!
fi
# end of './src/etherlocal.c'
fi
if test -f './src/etherread.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/etherread.c'\"
else
echo shar: Extracting \"'./src/etherread.c'\" \(1860 characters\)
sed "s/^X//" >'./src/etherread.c' <<'END_OF_FILE'
X/* $Id: etherread.c,v 2.1 89/10/23 15:42:40 dupuy Exp $ */
X
X#include <sys/types.h>			/* iovec (caddr_t) */
X#include <sys/uio.h>			/* iovec */
X
X#include <errno.h>			/* EWOULDBLOCK/EMSGSIZE */
X
Xextern int errno;
X
X#include "libether.h"
X
X#define HEADER	0
X#define DATA	1
X#define WASTE	2
X#define MAXIOV	3
X
X/*
X * Reads and returns a single packet, filling in all fields.  If pktbuf is
X * NULL, a buffer is allocated for it.	If pktbuf is not NULL, the function
X * assumes that pktbuf is large enough to hold pktlen bytes.  Reads on the
X * ethernet packet filter device always return one packet.  Streams must be in
X * RMSGD mode for reads to return one packet at a time
X */
X
Xint
Xether_read (fd, packet)
Xint fd;
Xether_packet *packet;
X{
X    char waste[ETHER_MAX];
X    struct iovec iov[MAXIOV];
X    int count;
X
X    iov[HEADER].iov_len = ETHER_PKT;
X    iov[HEADER].iov_base = (char *) packet;
X
X    if (packet->pktbuf)
X    {
X	iov[DATA].iov_len = packet->pktlen;
X	iov[DATA].iov_base = packet->pktbuf;
X
X	iov[WASTE].iov_len = sizeof (waste);
X	iov[WASTE].iov_base = waste;
X
X	count = 3;			/* use waste to get all of packet */
X    }
X    else
X    {
X	iov[DATA].iov_len = packet->pktlen = ETHER_MAX;
X	if ((iov[DATA].iov_base = (char *) malloc ((unsigned) ETHER_MAX)) == 0)
X	    return (-1);
X	packet->pktbuf = iov[DATA].iov_base;
X
X	count = 2;			/* no need to use waste */
X    }
X
X    if ((count = readv (fd, iov, count)) <= 0)
X    {
X#ifndef EBADMSG				/* a stream will return EAGAIN */
X	if (count == 0 || errno == EWOULDBLOCK)
X	    errno = EAGAIN;
X#endif
X	return (-1);
X    }
X
X    if ((count -= ETHER_PKT) < 0)
X    {					/* enet returns EOF (0) */
X#ifdef EBADMSG
X	errno = EBADMSG;		/* XXX readv() can also return this */
X#else
X	errno = EMSGSIZE;		/* XXX message isn't really too long */
X#endif
X    }
X    else if (packet->pktlen > count)
X	packet->pktlen = count;
X
X    return (count);
X}
END_OF_FILE
if test 1860 -ne `wc -c <'./src/etherread.c'`; then
    echo shar: \"'./src/etherread.c'\" unpacked with wrong size!
fi
# end of './src/etherread.c'
fi
if test -f './src/etherreadv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/etherreadv.c'\"
else
echo shar: Extracting \"'./src/etherreadv.c'\" \(1628 characters\)
sed "s/^X//" >'./src/etherreadv.c' <<'END_OF_FILE'
X/* $Id: etherreadv.c,v 2.1 89/10/23 15:42:42 dupuy Exp $ */
X
X#include <sys/types.h>			/* iovec (caddr_t) */
X#include <sys/uio.h>			/* iovec */
X
X#include <errno.h>			/* EWOULDBLOCK/EMSGSIZE */
X
Xextern int errno;
X
X#include "libether.h"
X
X#ifdef __GNUC__
X#define alloca __builtin_alloca
X#else
X#ifdef lint
Xextern double *dalloca ();
X#define alloca dalloca
X#else
X#ifdef sparc
X#include <alloca.h>
X#endif
Xextern char *alloca ();
X#endif
X#endif
X
X#define HEADER	0
X#define USER	1
X#define WASTE	(count - 1)
X
X/*
X * Reads and returns a single packet, filling in all fields.  Reads on the
X * ethernet packet filter device always return one packet.  Streams must be in
X * RMSGD mode for reads to return one packet at a time
X */
X
Xint
Xether_readv (fd, packet)
Xint fd;
Xether_vec *packet;
X{
X    char waste[ETHER_MAX];
X    int count = 2 + packet->iovcnt;
X    struct iovec *iov =
X	(struct iovec *) alloca (sizeof (struct iovec) * count);
X
X    iov[HEADER].iov_len = ETHER_PKT;
X    iov[HEADER].iov_base = (char *) packet;
X
X    (void) bcopy ((char *) packet->iov, (char *) &iov[USER],
X		  (int) packet->iovcnt * sizeof (struct iovec));
X
X    iov[WASTE].iov_len = sizeof (waste);
X    iov[WASTE].iov_base = waste;
X
X    if ((count = readv (fd, iov, count)) <= 0)
X    {					/* enet returns EOF (0) */
X#ifndef EBADMSG				/* a stream will return EAGAIN */
X	if (count == 0 || errno == EWOULDBLOCK)
X	    errno = EAGAIN;
X#endif
X	return (-1);
X    }
X
X    if ((count -= ETHER_PKT) < 0)
X    {
X#ifdef EBADMSG
X	errno = EBADMSG;		/* XXX readv() can also return this */
X#else
X	errno = EMSGSIZE;		/* XXX message isn't really too long */
X#endif
X    }
X
X    return (count);
X}
END_OF_FILE
if test 1628 -ne `wc -c <'./src/etherreadv.c'`; then
    echo shar: \"'./src/etherreadv.c'\" unpacked with wrong size!
fi
# end of './src/etherreadv.c'
fi
if test -f './src/libether.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/libether.h'\"
else
echo shar: Extracting \"'./src/libether.h'\" \(1312 characters\)
sed "s/^X//" >'./src/libether.h' <<'END_OF_FILE'
X/* $Id: libether.h,v 2.1 89/10/23 15:42:44 dupuy Exp $ */
X
X/* Internal definitions for ethernet access library */
X
X#include "ether.h"			/* get interface definitions */
X
X#define MAXNUMIF 16			/* maximum number of interfaces */
X
X#define ETHER_BUFFERS	5		/* for socket based NIT interface */
X#define ETHER_BUFSIZ \
X (ETHER_BUFFERS * (ETHER_PKT + ETHER_MAX + (2 * sizeof (struct nit_hdr))))
X
X#define ALIGNSIZE	(sizeof (int))
X#define pad(x)		((ALIGNSIZE - ((unsigned)(x)) % ALIGNSIZE) % ALIGNSIZE)
X
X#define address_check(dest) \
X (ETHER_MCAST (dest) \
X  && bcmp ((char *)(dest), (char *) &ether_bcast_addr, sizeof (ether_addr)) \
X  && bcmp ((char *)(dest), (char *) &_ether_multi_addrs[fd], \
X	   sizeof (ether_addr)))
X
X#ifdef __STDC__
X
Xextern char *malloc (unsigned size);
X
Xextern int _ether_arpscan (ether_addr *addr, struct in_addr *ipaddr);
Xextern int _ether_localif (ether_addr *addr, struct in_addr *ipaddr);
X#ifdef RARP
Xextern int _ether_rarpprobe (ether_addr *addr, struct in_addr *ipaddr);
X#endif
X
X#else
X
X#ifdef lint
X
X#ifndef htons
X
Xextern unsigned short htons ();
X
X#endif
X
X#ifdef ultrix
X
Xextern void bzero ();
Xextern void bcopy ();
Xextern void free ();
Xextern void perror ();
X
X#endif
X
Xextern double *dalloc ();
X#define malloc dalloc
X
X#else
X
Xextern char *malloc ();
X
X#endif /* lint */
X
X#endif /* __STDC__ */
END_OF_FILE
if test 1312 -ne `wc -c <'./src/libether.h'`; then
    echo shar: \"'./src/libether.h'\" unpacked with wrong size!
fi
# end of './src/libether.h'
fi
if test -f './src/nit3intaddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit3intaddr.c'\"
else
echo shar: Extracting \"'./src/nit3intaddr.c'\" \(1250 characters\)
sed "s/^X//" >'./src/nit3intaddr.c' <<'END_OF_FILE'
X/* $Id: nit3intaddr.c,v 2.1 89/10/23 15:42:47 dupuy Exp $ */
X
X#include <sys/types.h>			/* AF_NIT (u_short) */
X#include <sys/socket.h>			/* AF_NIT */
X
Xextern int errno;
X
X#include "libether.h"
X
Xether_addr _ether_localaddr;		/* shared with ether_address() */
Xint _ether_haveaddress;			/* shared with ether_address() */
X
X/*
X * Returns the local ethernet address for an ethernet interface.  The result
X * is stored in the structure given by address; if none is given, malloc is
X * used to allocate space.  Sun systems have the "feature" that all ethernet
X * interfaces are set to the same address (taken from the ID PROM).  So we can
X * get the answer once, and use it forever.
X */
X
X/* ARGSUSED */
X
Xether_addr *
Xether_intfaddr (intf, address)
Xchar *intf;
Xether_addr *address;
X{
X    if (!_ether_haveaddress)
X    {
X	int fd;
X	int saved_errno;
X
X	if ((fd = socket (AF_NIT, SOCK_RAW, 0)) < 0)
X	{
X#ifdef DEBUG
X	    perror ("ether_open: socket");
X#endif
X	    return (0);
X	}
X
X	address = ether_address (fd, address);
X
X	saved_errno = errno;
X	(void) close (fd);
X	errno = saved_errno;
X
X	return (address);
X    }
X
X    if (address == 0)
X	address = (ether_addr *) malloc (sizeof (ether_addr));
X
X    if (address != 0)
X	*address = _ether_localaddr;
X
X    return (address);
X}
END_OF_FILE
if test 1250 -ne `wc -c <'./src/nit3intaddr.c'`; then
    echo shar: \"'./src/nit3intaddr.c'\" unpacked with wrong size!
fi
# end of './src/nit3intaddr.c'
fi
if test -f './src/nit3read.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit3read.c'\"
else
echo shar: Extracting \"'./src/nit3read.c'\" \(1151 characters\)
sed "s/^X//" >'./src/nit3read.c' <<'END_OF_FILE'
X/* $Id: nit3read.c,v 2.1 89/10/23 15:42:53 dupuy Exp $ */
X
X#include "libether.h"
X
X/*
X * Reads and returns a single packet, filling in all fields.  If pktbuf is
X * NULL, a buffer is allocated for it.	If pktbuf is not NULL, the function
X * assumes that pktbuf is large enough to hold pktlen bytes.  Since read() may
X * return several packets at a time, we have to buffer them as well.  Since
X * socket based nit doesn't handle multicast addresses, we have to check them
X * at the user level.
X *
X * NOTE - the buffering code is not re-entrant, although different fd's will
X * not conflict.
X */
X
Xint
Xether_read (fd, packet)
Xint fd;
Xether_packet *packet;
X{
X    char *pbuf;
X    int bytes;
X
X    if ((bytes = _ether_next_packet (fd, &pbuf)) < 0)
X	return (-1);
X
X    bcopy (pbuf, (char *) packet, ETHER_PKT);
X    pbuf += ETHER_PKT;
X
X    if (packet->pktbuf == 0)
X    {
X	packet->pktlen = bytes;
X	if ((packet->pktbuf = (char *) malloc ((unsigned) bytes)) == 0)
X	    return (-1);
X    }
X
X    bcopy (pbuf, packet->pktbuf,
X	   (int) ((packet->pktlen > bytes) ? bytes : packet->pktlen));
X
X    if (packet->pktlen > bytes)
X	packet->pktlen = bytes;
X
X    return (bytes);
X}
END_OF_FILE
if test 1151 -ne `wc -c <'./src/nit3read.c'`; then
    echo shar: \"'./src/nit3read.c'\" unpacked with wrong size!
fi
# end of './src/nit3read.c'
fi
if test -f './src/nit3readv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit3readv.c'\"
else
echo shar: Extracting \"'./src/nit3readv.c'\" \(1251 characters\)
sed "s/^X//" >'./src/nit3readv.c' <<'END_OF_FILE'
X/* $Id: nit3readv.c,v 2.0 89/10/20 19:02:38 dupuy Exp $ */
X
X#include <sys/types.h>			/* iovec (caddr_t) */
X#include <sys/uio.h>			/* iovec */
X
X#include "libether.h"
X
X/*
X * Reads and returns a single packet, filling in all fields.  Since read() may
X * return several packets at a time, we have to buffer them as well.  Since
X * socket based nit doesn't handle multicast addresses, we have to check them
X * at the user level.
X *
X * NOTE - the buffering code is not re-entrant, although different fd's will
X * not conflict.
X */
X
Xint
Xether_readv (fd, packet)
Xint fd;
Xether_vec *packet;
X{
X    char *pbuf;
X    int index = 0;
X    int count;
X    int bytes;
X
X    if ((bytes = _ether_next_packet (fd, &pbuf)) < 0)
X	return (-1);
X
X    bcopy (pbuf, (char *) packet, ETHER_PKT);
X    pbuf += ETHER_PKT;
X
X    for (count = 0; count < packet->iovcnt && index < bytes; count++)
X	if (packet->iov[count].iov_len)
X	{
X	    if (bytes - index < packet->iov[count].iov_len)
X	    {
X		bcopy (&pbuf[index], (char *) packet->iov[count].iov_base,
X		       bytes - index);
X		break;
X	    }
X	    else
X	    {
X		bcopy (&pbuf[index], (char *) packet->iov[count].iov_base,
X		       (int) packet->iov[count].iov_len);
X		index += packet->iov[count].iov_len;
X	    }
X	}
X
X    return (bytes);
X}
END_OF_FILE
if test 1251 -ne `wc -c <'./src/nit3readv.c'`; then
    echo shar: \"'./src/nit3readv.c'\" unpacked with wrong size!
fi
# end of './src/nit3readv.c'
fi
if test -f './src/nit3self.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit3self.c'\"
else
echo shar: Extracting \"'./src/nit3self.c'\" \(396 characters\)
sed "s/^X//" >'./src/nit3self.c' <<'END_OF_FILE'
X/* $Id: nit3self.c,v 2.0 89/10/20 19:02:40 dupuy Exp $ */
X
X/*
X * No standard sun ethernet interface loops back packets. The socket-based Sun
X * NIT interface doesn't do it either.
X */
X
X/* ARGSUSED */
X
Xint
Xether_send_self (fd)
Xint fd;
X{
X    return (0);
X}
X
X/* ARGSUSED */
X
Xint
Xether_mcast_self (fd)
Xint fd;
X{
X    return (0);
X}
X
X/* ARGSUSED */
X
Xint
Xether_bcast_self (fd)
Xint fd;
X{
X    return (0);
X}
END_OF_FILE
if test 396 -ne `wc -c <'./src/nit3self.c'`; then
    echo shar: \"'./src/nit3self.c'\" unpacked with wrong size!
fi
# end of './src/nit3self.c'
fi
if test -f './src/nit3write.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit3write.c'\"
else
echo shar: Extracting \"'./src/nit3write.c'\" \(681 characters\)
sed "s/^X//" >'./src/nit3write.c' <<'END_OF_FILE'
X/* $Id: nit3write.c,v 2.0 89/10/20 19:02:41 dupuy Exp $ */
X
X#include <sys/param.h>
X#include <sys/socket.h>
X
X#include "libether.h"
X
Xextern unsigned _ether_types[NOFILE];
X
X#define ether_type (_ether_types[fd])
X
X/*
X * Writes a single packet, filling src and type fields.
X */
X
Xint
Xether_write (fd, packet)
Xint fd;
Xether_packet *packet;
X{
X    struct sockaddr sa;
X
X    sa.sa_family = AF_UNSPEC;
X    bcopy ((char *) packet, sa.sa_data, ETHER_TYPE);
X
X    if (ether_type != ETHER_ALLTYPES)
X    {
X	sa.sa_data[12] = (ether_type >> 8) & 0xff;
X	sa.sa_data[13] = ether_type & 0xff;
X    }
X
X    return (sendto (fd, packet->pktbuf, (int) packet->pktlen, 0, &sa,
X		    sizeof (sa)) < 0 ? -1 : 0);
X}
END_OF_FILE
if test 681 -ne `wc -c <'./src/nit3write.c'`; then
    echo shar: \"'./src/nit3write.c'\" unpacked with wrong size!
fi
# end of './src/nit3write.c'
fi
if test -f './src/nit3writev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit3writev.c'\"
else
echo shar: Extracting \"'./src/nit3writev.c'\" \(844 characters\)
sed "s/^X//" >'./src/nit3writev.c' <<'END_OF_FILE'
X/* $Id: nit3writev.c,v 2.0 89/10/20 19:02:42 dupuy Exp $ */
X
X#include <sys/param.h>
X#include <sys/socket.h>
X
X#include "libether.h"
X
Xextern unsigned _ether_types[NOFILE];
X
X#define ether_type (_ether_types[fd])
X
X/*
X * Writes a single packet, filling src and type fields.
X */
X
Xint
Xether_writev (fd, packet)
Xint fd;
Xether_vec *packet;
X{
X    struct sockaddr sa;
X    struct msghdr msg;
X
X    sa.sa_family = AF_UNSPEC;
X    bcopy ((char *) packet, sa.sa_data, ETHER_TYPE);
X
X    if (ether_type != ETHER_ALLTYPES)
X    {
X	sa.sa_data[12] = (ether_type >> 8) & 0xff;
X	sa.sa_data[13] = ether_type & 0xff;
X    }
X
X    msg.msg_iov = packet->iov;
X    msg.msg_iovlen = packet->iovcnt;
X    msg.msg_name = (caddr_t) & sa;
X    msg.msg_namelen = sizeof (sa);
X    msg.msg_accrights = 0;
X    msg.msg_accrightslen = 0;
X
X    return (sendmsg (fd, &msg, 0) < 0 ? -1 : 0);
X}
END_OF_FILE
if test 844 -ne `wc -c <'./src/nit3writev.c'`; then
    echo shar: \"'./src/nit3writev.c'\" unpacked with wrong size!
fi
# end of './src/nit3writev.c'
fi
if test -f './src/nit4intaddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit4intaddr.c'\"
else
echo shar: Extracting \"'./src/nit4intaddr.c'\" \(1809 characters\)
sed "s/^X//" >'./src/nit4intaddr.c' <<'END_OF_FILE'
X/* $Id: nit4intaddr.c,v 2.1 89/10/23 15:42:56 dupuy Exp $ */
X
X#include <strings.h>			/* strncpy */
X#include <sys/file.h>			/* O_RDWR */
X#include <sys/types.h>			/* NIOCBIND (u_long) */
X#include <sys/time.h>			/* NIOCBIND (timeval) */
X#include <sys/ioccom.h>			/* ioctl */
X#include <sys/socket.h>			/* ifreq (sockaddr) */
X
X#include <net/if.h>			/* ifreq */
X#include <net/nit_if.h>			/* NIOCBIND */
X
X#include "libether.h"
X
Xextern int errno;
X
X#ifndef NIT_DEV
X#define NIT_DEV "/dev/nit"
X#endif
X
Xether_addr _ether_localaddr;		/* shared with ether_address() */
Xint _ether_haveaddress;			/* shared with ether_address() */
X
X/*
X * Returns the local ethernet address for an ethernet interface.  The result
X * is stored in the structure given by address; if none is given, malloc is
X * used to allocate space.  Sun systems have the "feature" that all ethernet
X * interfaces are set to the same address (taken from the ID PROM).  So we can
X * get the answer once, and use it forever.
X */
X
Xether_addr *
Xether_intfaddr (intf, address)
Xchar *intf;
Xether_addr *address;
X{
X    if (!_ether_haveaddress)
X    {
X	int fd;
X	struct ifreq ifr;
X	int saved_errno;
X
X	if ((fd = open (NIT_DEV, O_RDWR)) < 0)
X	{
X#ifdef DEBUG
X	    perror (NIT_DEV);
X#endif
X	    return (0);
X	}
X
X	(void) strncpy (ifr.ifr_name, intf, sizeof (ifr.ifr_name));
X
X	if (ioctl (fd, NIOCBIND, (char *) &ifr) < 0)
X	{
X	    saved_errno = errno;
X#ifdef DEBUG
X	    perror ("ether_intfaddr: ioctl NIOCBIND");
X#endif
X	    (void) close (fd);
X	    errno = saved_errno;
X	    return (0);
X	}
X
X	address = ether_address (fd, address);
X
X	saved_errno = errno;
X	(void) close (fd);
X	errno = saved_errno;
X
X	return (address);
X    }
X
X    if (address == 0)
X	address = (ether_addr *) malloc (sizeof (ether_addr));
X
X    if (address != 0)
X	*address = _ether_localaddr;
X
X    return (address);
X}
END_OF_FILE
if test 1809 -ne `wc -c <'./src/nit4intaddr.c'`; then
    echo shar: \"'./src/nit4intaddr.c'\" unpacked with wrong size!
fi
# end of './src/nit4intaddr.c'
fi
if test -f './src/nit4self.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit4self.c'\"
else
echo shar: Extracting \"'./src/nit4self.c'\" \(894 characters\)
sed "s/^X//" >'./src/nit4self.c' <<'END_OF_FILE'
X/* $Id: nit4self.c,v 2.0 89/10/20 19:02:46 dupuy Exp $ */
X
X#include <sys/sockio.h>			/* SIOCGETFDSTAT */
X
X/*
X * No standard sun ethernet interface loops back packets.  Early versions of
X * the streams-based Sun NIT interface don't loopback broadcast packets, but
X * 4.0.3 and later appear to (although 4.0.3 has bugs).	 Since a 4.0 compiled
X * binary will run on a 4.0.3 system, we can't determine the answer correctly
X * at compile time.  Since there doesn't seem to be any kernel feature present
X * in 4.0.3 and absent in earlier versions that we can test for, we use a
X * compile-time check.	It's the best we can do for now.
X */
X
X/* ARGSUSED */
X
Xint
Xether_send_self (fd)
Xint fd;
X{
X    return (0);
X}
X
X/* ARGSUSED */
X
Xint
Xether_mcast_self (fd)
Xint fd;
X{
X    return (0);
X}
X
X/* ARGSUSED */
X
Xint
Xether_bcast_self (fd)
Xint fd;
X{
X#ifdef SIOCGETFDSTAT
X    return (1);
X#else
X    return (0);
X#endif
X}
END_OF_FILE
if test 894 -ne `wc -c <'./src/nit4self.c'`; then
    echo shar: \"'./src/nit4self.c'\" unpacked with wrong size!
fi
# end of './src/nit4self.c'
fi
if test -f './src/nit4write.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit4write.c'\"
else
echo shar: Extracting \"'./src/nit4write.c'\" \(956 characters\)
sed "s/^X//" >'./src/nit4write.c' <<'END_OF_FILE'
X/* $Id: nit4write.c,v 2.0 89/10/20 19:02:47 dupuy Exp $ */
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/stropts.h>
X
X#include "libether.h"
X
Xextern unsigned _ether_types[FD_SETSIZE];
X
X#define ether_type (_ether_types[fd])
X
X/*
X * Writes a single packet, filling src and type fields.
X */
X
Xint
Xether_write (fd, packet)
Xint fd;
Xether_packet *packet;
X{
X    struct sockaddr sa;
X    struct strbuf cbuf;
X    struct strbuf dbuf;
X
X    sa.sa_family = AF_UNSPEC;
X    bcopy ((char *) packet, sa.sa_data, ETHER_TYPE);
X
X    if (ether_type != ETHER_ALLTYPES)
X    {
X	sa.sa_data[12] = (ether_type >> 8) & 0xff;
X	sa.sa_data[13] = ether_type & 0xff;
X    }
X
X    cbuf.maxlen = cbuf.len = sizeof (sa);
X    cbuf.buf = (char *) &sa;
X
X    /*
X     * The interface output routines will paste the ether header back onto the
X     * front of the message.
X     */
X
X    dbuf.len = packet->pktlen;
X    dbuf.buf = packet->pktbuf;
X
X    return (putmsg (fd, &cbuf, &dbuf, 0));
X}
END_OF_FILE
if test 956 -ne `wc -c <'./src/nit4write.c'`; then
    echo shar: \"'./src/nit4write.c'\" unpacked with wrong size!
fi
# end of './src/nit4write.c'
fi
if test -f './src/nit4writev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nit4writev.c'\"
else
echo shar: Extracting \"'./src/nit4writev.c'\" \(1172 characters\)
sed "s/^X//" >'./src/nit4writev.c' <<'END_OF_FILE'
X/* $Id: nit4writev.c,v 2.0 89/10/20 19:02:48 dupuy Exp $ */
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/stropts.h>
X#include <sys/uio.h>
X
X#include "libether.h"
X
Xextern unsigned _ether_types[FD_SETSIZE];
X
X#define ether_type (_ether_types[fd])
X
X/*
X * Writes a single packet, filling src and type fields.
X */
X
Xint
Xether_writev (fd, packet)
Xint fd;
Xether_vec *packet;
X{
X    struct sockaddr sa;
X    struct strbuf cbuf;
X    struct strbuf dbuf;
X    char buffer[ETHER_MAX];
X    char *bufp = buffer;
X    int count;
X
X    sa.sa_family = AF_UNSPEC;
X    bcopy ((char *) packet, sa.sa_data, ETHER_TYPE);
X
X    if (ether_type != ETHER_ALLTYPES)
X    {
X	sa.sa_data[12] = (ether_type >> 8) & 0xff;
X	sa.sa_data[13] = ether_type & 0xff;
X    }
X
X    cbuf.maxlen = cbuf.len = sizeof (sa);
X    cbuf.buf = (char *) &sa;
X
X    dbuf.len = 0;
X    dbuf.buf = bufp;
X
X    for (count = 0; count < packet->iovcnt; count++)
X	if (packet->iov[count].iov_len)
X	{
X	    bcopy ((char *) packet->iov[count].iov_base, bufp,
X		   (int) packet->iov[count].iov_len);
X	    bufp += packet->iov[count].iov_len;
X	    dbuf.len += packet->iov[count].iov_len;
X	}
X
X    return (putmsg (fd, &cbuf, &dbuf, 0));
X}
END_OF_FILE
if test 1172 -ne `wc -c <'./src/nit4writev.c'`; then
    echo shar: \"'./src/nit4writev.c'\" unpacked with wrong size!
fi
# end of './src/nit4writev.c'
fi
if test -f './src/nitaddr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./src/nitaddr.c'\"
else
echo shar: Extracting \"'./src/nitaddr.c'\" \(1351 characters\)
sed "s/^X//" >'./src/nitaddr.c' <<'END_OF_FILE'
X/* $Id: nitaddr.c,v 2.1 89/10/23 15:43:02 dupuy Exp $ */
X
X#include <sys/types.h>			/* ifreq (u_short) */
X#include <sys/socket.h>			/* ifreq (sockaddr) */
X#include <net/if.h>			/* ifreq */
X#include <sys/ioctl.h>			/* SIOCGIFADDR */
X
X#include "libether.h"
X
Xether_addr _ether_localaddr;		/* shared with ether_intfaddr() */
Xint _ether_haveaddress;			/* shared with ether_intfaddr() */
X
X/*
X * Returns the local ethernet address for the ethernet interface on the file
X * descriptor fd.  The result is stored in the structure given by address; if
X * none is given, malloc is used to allocate space.  Sun systems have the
X * "feature" that all ethernet interfaces are set to the same address (taken
X * from the ID PROM).  So we can get the answer once, and use it forever.
X */
X
Xether_addr *
Xether_address (fd, address)
Xint fd;
Xether_addr *address;
X{
X    if (!_ether_haveaddress)
X    {
X	struct ifreq ifr;
X
X	ifr.ifr_addr.sa_family = AF_NIT;
X	if (ioctl (fd, SIOCGIFADDR, (char *) &ifr) < 0)
X	{
X#ifdef DEBUG
X	    perror ("ether_address: ioctl SIOCGIFADDR");
X#endif
X	    return (0);
X	}
X
X	bcopy (ifr.ifr_addr.sa_data, (char *) &_ether_localaddr,
X	       sizeof (ether_addr));
X
X	_ether_haveaddress = 1;
X    }
X
X    if (address == 0)
X	address = (ether_addr *) malloc (sizeof (ether_addr));
X
X    if (address != 0)
X	*address = _ether_localaddr;
X
X    return (address);
X}
END_OF_FILE
if test 1351 -ne `wc -c <'./src/nitaddr.c'`; then
    echo shar: \"'./src/nitaddr.c'\" unpacked with wrong size!
fi
# end of './src/nitaddr.c'
fi
if test -f './system' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./system'\"
else
echo shar: Extracting \"'./system'\" \(1175 characters\)
sed "s/^X//" >'./system' <<'END_OF_FILE'
X#!/bin/sh
X#
X# Determine the current system platform
X#
Xif [ -s /bin/arch -a -s /bin/sun ]; then	# Sun's arch
X	ARCH=`/bin/arch`
X
Xelif [ -s /bin/machine ]; then			# MIPS' machine
X	ARCH=`/bin/machine`
X
Xelif [ -f /bin/vax ] && /bin/vax; then
X	ARCH=vax
X
Xelif [ "`echo /bin/hp*`" != '/bin/hp*' ]; then	# HP's way
X	{ /bin/hp9000s800 && ARCH=hp800; } || \
X	{ /bin/hp9000s500 && ARCH=hp500; } || \
X	{ /bin/hp9000s300 && ARCH=hp300; } || \
X	{ /bin/hp9000s200 && ARCH=hp200; } || \
X	{ /bin/hp300 && ARCH=hp300; } || \
X	{ /bin/hp800 && ARCH=hp800; }		# Utah HP 4.3
X
Xelif [ -d /usr/ibm -o -d /vrm ]; then		# IBM AIX or ACIS
X	ARCH=ibmrt
X
Xelif [ -d /NextLibrary ]; then			# Unique to NeXT cubes
X	ARCH=next
X
Xelif [ -d /usr/ucb ]; then			# desperation time
X	ARCH=vax
Xfi
X
Xcase $ARCH in
X
X	hp*)
X		if [ -f /hp-ux ]; then
X			OS=hpux
X		fi;;
X
X	ibmrt)
X		if [ -d /vrm ]; then
X			OS=aix
X		fi;;
X
X	mips*)
X		if [ -f /ultrixboot ]; then
X			ARCH=mipsel
X			OS=ultrix
X		fi;;
X
X	sun[234])
X		if [ -f /usr/ucb/logger ]; then
X			OS=os4
X		elif [ -d /usr/suntools ]; then
X			OS=os2
X		fi;;
X
X	next)	OS=mach;;
X
X	vax)
X		if [ -f /ultrixboot ]; then
X			OS=ultrix
X		fi;;
X
X	*)	ARCH=unknown;;
X
Xesac
X
Xexec echo $ARCH${OS+-$OS}
END_OF_FILE
if test 1175 -ne `wc -c <'./system'`; then
    echo shar: \"'./system'\" unpacked with wrong size!
fi
# end of './system'
fi
if test ! -d './tests' ; then
    echo shar: Creating directory \"'./tests'\"
    mkdir './tests'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.