home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
kboot22.zoo
/
kboot22.1
/
nitlib.c
< prev
Wrap
C/C++ Source or Header
|
1991-02-22
|
6KB
|
270 lines
#ifndef lint
static char *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/nitlib.c,v 1.2 91/02/12 19:38:10 root Exp $";
#endif lint
/*
* $Log: nitlib.c,v $
* Revision 1.2 91/02/12 19:38:10 root
* Don't call fdfunc() if NULL.
*
* Revision 1.1 91/01/29 17:37:28 root
* Initial revision
*
*/
#include <stdio.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stropts.h>
#include <net/nit_if.h>
#include <net/nit_pf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <net/packetfilt.h>
#include "config.h"
#define MAXPKT 1500
#define OFFSET(t,f) ((int) &(((t *) NULL)->f))
extern char *malloc ();
extern char *strdup ();
extern int debug;
extern int detached;
extern int errno;
extern char *sys_errlist[];
/*
* Globals.
*/
struct ether_addr myether;
int nit_fd;
char nitbuf[MAXPKT];
int numfds;
char *interface;
/*
* nit_init - Initialize nit library.
*/
nit_init (dev)
char *dev;
{
struct ifconf ifc;
int s;
char buf[BUFSIZ];
numfds = getdtablesize ();
if (dev == NULL) {
if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
logerr ("nit_init: socket - %s\n", sys_errlist[errno]);
exit(1);
}
ifc.ifc_len = BUFSIZ;
ifc.ifc_buf = buf;
if (ioctl (s, SIOCGIFCONF, (caddr_t) &ifc) < 0) {
logerr ("nit_init: ioctl(SIOCGIFCONF) - %s\n", sys_errlist[errno]);
exit(1);
}
close(s);
interface = strdup (ifc.ifc_req->ifr_name);
} else
interface = dev;
if (debug)
fprintf (stderr, "nit_init: Using interface %s\n", interface);
}
/*
* nit_open - Open NIT device and bind to an interface.
* Prints an error and exits if there's a problem.
*/
nit_open (snaplen, pkttype)
int snaplen;
int pkttype;
{
int s;
struct packetfilt pf;
u_short *pfp;
struct ifreq ifr;
if ((nit_fd = open ("/dev/nit", O_RDWR)) < 0) { /* Open NIT dev */
logerr ("nit_open: open(/dev/nit) - %s\n", sys_errlist[errno]);
exit (1);
}
if (ioctl (nit_fd, I_SRDOPT, (caddr_t) RMSGD) < 0) { /* Discrete msgs*/
logerr ("nit_open: ioctl(I_SRDOPT) - %s\n", sys_errlist[errno]);
exit (1);
}
if (pkttype) {
if (ioctl (nit_fd, I_PUSH, "pf") < 0) { /* Setup packet filter */
logerr ("nit_open: ioctl(I_PUSH: pf) - %s\n", sys_errlist[errno]);
exit (1);
}
pfp = pf.Pf_Filter;
*pfp++ = ENF_PUSHWORD +
OFFSET (struct ether_header, ether_type) / sizeof (u_short);
*pfp++ = ENF_PUSHLIT | ENF_EQ;
*pfp++ = htons (pkttype);
pf.Pf_FilterLen = ((int) pfp - (int) pf.Pf_Filter) / sizeof (u_short);
if (ioctl (nit_fd, NIOCSETF, (caddr_t) &pf) < 0) {
logerr ("nit_open: ioctl(NIOCSETF) - %s\n", sys_errlist[errno]);
exit (1);
}
}
strncpy (ifr.ifr_name, interface, sizeof ifr.ifr_name);
ifr.ifr_name[sizeof ifr.ifr_name - 1] = '\0';
if (ioctl (nit_fd, NIOCBIND, &ifr) < 0) {
logerr ("nit_open: ioctl(NIOCBIND) - %s\n", sys_errlist[errno]);
exit(1);
}
/* Get ethernet address */
if (ioctl (nit_fd, SIOCGIFADDR, (caddr_t) &ifr) < 0) {
logerr ("nit_open: ioctl(SIOCGIFADDR) - %s\n", sys_errlist[errno]);
exit (1);
}
ether_copy (ifr.ifr_addr.sa_data, &myether);
if (snaplen > 0) { /* Set snapshot length */
if (ioctl (nit_fd, NIOCSSNAP, (caddr_t) &snaplen) < 0) {
logerr ("nit_open: ioctl (NIOCSSNAP) - %s\n", sys_errlist[errno]);
exit (1);
}
}
}
/*
* nit_close - Close nit file descriptor.
*/
nit_close ()
{
close (nit_fd);
}
/*
* timeout - Return timeval structure for timeout specified in ticks for
* reads from nit device. Ticks are 1/60 of a second. A timeout of 0
* means reads will not timeout.
*/
nit_timeout (ticks, tv)
int ticks;
struct timeval *tv;
{
tv->tv_sec = ticks / 60; /* Set timeout */
tv->tv_usec = ((ticks * 1000000) / 60) % 1000000;
}
/*
* nit_write - Send a raw ethernet packet.
*/
nit_write (eh, pkt, len)
struct ether_header *eh;
caddr_t pkt;
int len;
{
struct sockaddr sa;
struct strbuf cbuf;
struct strbuf dbuf;
sa.sa_family = AF_UNSPEC;
bcopy (eh, sa.sa_data, sizeof (*eh));
cbuf.len = sizeof sa;
cbuf.buf = (caddr_t) &sa;
dbuf.len = len;
dbuf.buf = pkt;
if (putmsg (nit_fd, &cbuf, &dbuf, 0) < 0) {
logerr ("nit_write: putmsg - %s\n", sys_errlist[errno]);
exit (1);
}
}
/*
* nit_dispatch - Read and process n packets. If n is 0 read forever.
* Calls "func" for each packet with the arguments:
*
* (*func) (pp, pl)
* pp = packet pointer
* pl = length of packet
*
* If an application is waiting for input on other file descriptors
* they can be specified in "fds". "fdfunc" will be called with
* the set of descriptors that have input waiting before the current
* packet is processed. Returns 0 on timeout, 1 otherwise.
*/
int nit_dispatch (func, n, fds, fdfunc, timeout)
int (*func)();
int n;
fd_set *fds;
int (*fdfunc)();
struct timeval *timeout;
{
int i;
int numpkts;
fd_set fdset;
fd_set rfds;
numpkts = 0;
if (fds)
fdset = *fds;
else
FD_ZERO (&fdset);
FD_SET (nit_fd, &fdset);
while (n == 0 || numpkts < n) {
rfds = fdset;
i = select (numfds, &rfds, NULL, NULL, timeout);
if (i == 0)
return (0); /* Timeout */
if (FD_ISSET (nit_fd, &rfds)) {
numpkts++;
FD_CLR (nit_fd, &rfds);
if (i > 1)
(*fdfunc) (&rfds);
} else if (fdfunc) {
(*fdfunc) (&rfds);
continue;
}
if ((i = read (nit_fd, nitbuf, MAXPKT)) < 0) {
lseek (nit_fd, 0, 0); /* File pointer may've wrapped */
if ((i = read (nit_fd, nitbuf, MAXPKT)) < 0) {
logerr ("nit_dispatch: read - %s\n", sys_errlist[errno]);
exit (1);
}
}
(*func) (nitbuf, i);
}
return (1);
}
/*
* logerr - Log error to stderr (if debug) or syslog.
*/
logerr (fmt, a1, a2, a3)
char *fmt;
char *a1;
char *a2;
char *a3;
{
if (detached)
syslog (LOG_ERR, fmt, a1, a2, a3);
else
fprintf (stderr, fmt, a1, a2, a3);
}