pseudo-device clone pseudo-device snit pseudo-device pf pseudo-device nbuf
#include <sys/file.h> #include <sys/ioctl.h> #include <net/nit_pf.h> #include <net/nit_buf.h> fd = open("/dev/nit", mode); ioctl(fd, I_PUSH, "pf"); ioctl(fd, I_PUSH, "nbuf");
NIT (the Network Interface Tap) is a facility composed of several STREAMS modules and drivers. These components collectively provide facilities for constructing applications that require link-level network access. Examples of such applications include rarpd.8c which is a user-level implementation of the Reverse ARP protocol, and etherfind.8c which is a network monitoring and trouble-shooting program.
NIT consists of several components that are summarized below. See their Reference Manual entries for detailed information about their specification and operation.
NIT clients mix and match these components, based on their particular requirements. For example, the reverse ARP daemon concerns itself only with packets of a specific type and deals with low traffic volumes. Thus, it uses nit_if for access to the network and nit_pf to filter out all incoming packets except reverse ARP packets, but omits the nit_buf buffering module since traffic is not high enough to justify the additional complexity of unpacking buffered packets. On the other hand, the etherd.8c program, which collects Ethernet statistics for traffic.1c to display, must examine every packet on the network. Therefore, it omits the nit_pf module, since there is nothing it wishes to screen out, and includes the nit_buf module, since most networks have very heavy aggregate packet traffic.
The following code fragments outline how to program against parts of the NIT interface. For the sake of brevity, all error-handling code has been elided.
initdevice comes from etherfind and sets up its input stream configuration.
initdevice(if_flags, snaplen, chunksize) u_long if_flags, snaplen, chunksize;
{ struct strioctl si; struct ifreq ifr; struct timeval timeout; if_fd = open(NIT_DEV, O_RDONLY); /* Arrange to get discrete messages from the stream. */ ioctl(if_fd, I_SRDOPT, (char *)RMSGD); si.ic_timout = INFTIM; /* Push and configure the buffering module. */ ioctl(if_fd, I_PUSH, "nbuf"); timeout.tv_sec = 1; timeout.tv_usec = 0; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof timeout; si.ic_dp = (char *)&timeout; ioctl(if_fd, I_STR, (char *)&si); si.ic_cmd = NIOCSCHUNK; si.ic_len = sizeof chunksize; si.ic_dp = (char *)&chunksize; ioctl(if_fd, I_STR, (char *)&si); /* Configure the nit device, binding it to the proper underlying interface, setting the snapshot length, and setting nit_if-level flags. */ strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name); ifr.ifr_name[sizeof ifr.ifr_name - 1] = '\0'; si.ic_cmd = NIOCBIND; si.ic_len = sizeof ifr; si.ic_dp = (char *)𝔦 ioctl(if_fd, I_STR, (char *)&si); if (snaplen > 0) { si.ic_cmd = NIOCSSNAP; si.ic_len = sizeof snaplen; si.ic_dp = (char *)&snaplen; ioctl(if_fd, I_STR, (char *)&si); } if (if_flags != 0) { si.ic_cmd = NIOCSFLAGS; si.ic_len = sizeof if_flags; si.ic_dp = (char *)&if_flags; ioctl(if_fd, I_STR, (char *)&si); } /* Flush the read queue, to get rid of anything that accumulated before the device reached its final configuration. */ ioctl(if_fd, I_FLUSH, (char *)FLUSHR); }
Here is the skeleton of the packet reading loop from etherfind. It illustrates how to cope with dismantling the headers the various NIT components glue on.
while ((cc = read(if_fd, buf, chunksize)) >= 0) { register u_char *bp = buf, *bufstop = buf + cc; /* Loop through each message in the chunk. */ while (bp < bufstop) { register u_char *cp = bp; struct nit_bufhdr *hdrp; struct timeval *tvp = NULL; u_long drops = 0; u_long pktlen; /* Extract information from the successive objects embedded in the current message. Which ones we have depends on how we set up the stream (and therefore on what command line flags were set). If snaplen is positive then the packet was truncated before the buffering module saw it, so we must obtain its length from the nit_if-level nit_iflen header. Otherwise the value in *hdrp suffices. */ hdrp = (struct nit_bufhdr *)cp; cp += sizeof *hdrp; if (tflag) { struct nit_iftime *ntp; ntp = (struct nit_iftime *)cp; cp += sizeof *ntp; tvp = &ntp->nh_timestamp; } if (dflag) { struct nit_ifdrops *ndp; ndp = (struct nit_ifdrops *)cp; cp += sizeof *ndp; drops = ndp->nh_drops; } if (snaplen > 0) { struct nit_iflen *nlp; nlp = (struct nit_iflen *)cp; cp += sizeof *nlp; pktlen = nlp->nh_pktlen; } else pktlen = hdrp->nhb_msglen; sp = (struct sample *)cp; bp += hdrp->nhb_totlen; /* Process the packet. */ } }
Created by unroff & hp-tools. © somebody (See intro for details). All Rights Reserved. Last modified 11/5/97