NIT(4P) PROTOCOLS NIT(4P) NAME nit - Network Interface Tap CONFIG pseudo-device clone pseudo-device snit pseudo-device pf pseudo-device nbuf SYNOPSIS #include #include #include #include fd = open("/dev/nit", mode); ioctl(fd, I_PUSH, "pf"); ioctl(fd, I_PUSH, "nbuf"); DESCRIPTION NIT (the Network Interface Tap) is a facility composed of several STREAMS modules and drivers. These components col- lectively provide facilities for constructing applications that require link-level network access. Examples of such applications include rarpd(8C), which is a user-level imple- mentation 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_if(4M) This component is a STREAMS device driver that interacts directly with the system's Ethernet drivers. After opening an instance of this dev- ice it must be bound to a specific Ethernet interface before becoming usable. Subsequently, nit_if transcribes packets arriving on the interface to the read side of its associated stream and delivers messages reaching it on the write side of its stream to the raw packet out- put code for transmission over the interface. nit_pf(4M) This module provides packet-filtering services, allowing uninteresting incoming packets to be discarded with minimal loss of efficiency. It passes through unaltered all outgoing messages (those on the stream's write side). nit_buf(4M) This module buffers incoming messages into larger aggregates, thereby reducing the overhead incurred by repeated read(2V) system calls. Sun Release 4.1 Last change: 29 December 1987 1 NIT(4P) PROTOCOLS NIT(4P) NIT clients mix and match these components, based on their particular requirements. For example, the reverse ARP dae- mon 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 Eth- ernet 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. EXAMPLES 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; Sun Release 4.1 Last change: 29 December 1987 2 NIT(4P) PROTOCOLS NIT(4P) 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 ether- find. 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). Sun Release 4.1 Last change: 29 December 1987 3 NIT(4P) PROTOCOLS NIT(4P) 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. */ } } FILES /dev/nit clone device instance referring to nit_if SEE ALSO traffic(1C), read(2V), nit_if(4M), nit_pf(4M), nit_buf(4M), etherd(8C), etherfind(8C), rarpd(8C) Sun Release 4.1 Last change: 29 December 1987 4