home *** CD-ROM | disk | FTP | other *** search
- /* $Id: etherread.c,v 2.1 89/10/23 15:42:40 dupuy Exp $ */
-
- #include <sys/types.h> /* iovec (caddr_t) */
- #include <sys/uio.h> /* iovec */
-
- #include <errno.h> /* EWOULDBLOCK/EMSGSIZE */
-
- extern int errno;
-
- #include "libether.h"
-
- #define HEADER 0
- #define DATA 1
- #define WASTE 2
- #define MAXIOV 3
-
- /*
- * Reads and returns a single packet, filling in all fields. If pktbuf is
- * NULL, a buffer is allocated for it. If pktbuf is not NULL, the function
- * assumes that pktbuf is large enough to hold pktlen bytes. Reads on the
- * ethernet packet filter device always return one packet. Streams must be in
- * RMSGD mode for reads to return one packet at a time
- */
-
- int
- ether_read (fd, packet)
- int fd;
- ether_packet *packet;
- {
- char waste[ETHER_MAX];
- struct iovec iov[MAXIOV];
- int count;
-
- iov[HEADER].iov_len = ETHER_PKT;
- iov[HEADER].iov_base = (char *) packet;
-
- if (packet->pktbuf)
- {
- iov[DATA].iov_len = packet->pktlen;
- iov[DATA].iov_base = packet->pktbuf;
-
- iov[WASTE].iov_len = sizeof (waste);
- iov[WASTE].iov_base = waste;
-
- count = 3; /* use waste to get all of packet */
- }
- else
- {
- iov[DATA].iov_len = packet->pktlen = ETHER_MAX;
- if ((iov[DATA].iov_base = (char *) malloc ((unsigned) ETHER_MAX)) == 0)
- return (-1);
- packet->pktbuf = iov[DATA].iov_base;
-
- count = 2; /* no need to use waste */
- }
-
- if ((count = readv (fd, iov, count)) <= 0)
- {
- #ifndef EBADMSG /* a stream will return EAGAIN */
- if (count == 0 || errno == EWOULDBLOCK)
- errno = EAGAIN;
- #endif
- return (-1);
- }
-
- if ((count -= ETHER_PKT) < 0)
- { /* enet returns EOF (0) */
- #ifdef EBADMSG
- errno = EBADMSG; /* XXX readv() can also return this */
- #else
- errno = EMSGSIZE; /* XXX message isn't really too long */
- #endif
- }
- else if (packet->pktlen > count)
- packet->pktlen = count;
-
- return (count);
- }
-