Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

bind(2)

config(8)

ec(4S)

ie(4S)

if(4N)

ioctl(2)

read(2V)

recv(2)

send(2)

socket(2)

write(2V)

NIT(4P)  —  SPECIAL FILES

NAME

nit − Network Interface Tap Protocol

SYNOPSIS

options NIT

DESCRIPTION

nit is a provisional protocol familty which runs on top of the kernel raw socket code and provides the superuser with a tee connection into a specified network interface.  For example, it provides the unprocessed packet read and write capability on the Ethernet interface ie(4S).

nit uses two structures to communicate information, the nit_ioc structure, which contains the ioctl information used to set parameter values; and the nit_hdr structure, which contains per packet statistics and is prepended to every delivered packet.  When setting parameters, values that are otherwise impossible mean "don’t change". 

nit collects incoming packets into chunks to reduce the per packet overhead.  The chunks are returned by read(2V) and recv(2) system calls.  Outgoing packets are not buffered.  The ioctl value nioc_chunksize sets the size of the incoming chunk.  Nioc_bufalign and nioc_bufoffset control packet placement within buffers.  The (nit) header for each packet in a buffer starts nioc_bufoffset bytes past some multiple of nioc_bufalign bytes from the beginning.  The packet itself appears immediately beyond the header.  nit also limits the amount of buffer space consumed.  To change the default, set nioc_bufspace.

nit performs packet filtering and data selection on incoming packets.  The data selection criterion is the length of the initial portion of the data packet to return to the user.  The filtering criteria are packet destination and packet type.  The filtering and data selection criteria are set via nioc_snaplen, nioc_flags, and nioc_typetomatch. The choices for destination are either normal or promiscuous. Normal destination filtering considers only those packets that are normally received by the machine running nit (both host specific and broadcast packets).  Promiscuous destination filtering considers every packet visible on the network; this can place a large demand on the processor if there are many packets to receive.  The packets are further filtered on type, an interface specific quantity.  For the Ethernet interfaces, the type field is the packet type from the Ethernet header.  See <netinet/if_ether.h>.

Outgoing packets are not (yet) handled in a general way, since there is no one address family which says "send the packet as is", where the data portion of the packet contains a complete packet to be transmitted without further processing.  Therefore, in general, you can’t send arbitrary packets.  For the Ethernet, however, the address family AF_UNSPEC is defined so that the remaining 14 bytes of the sockaddr correspond the the first 14 bytes of the outgoing packet, which are the (6 byte) destination address, the (6 byte) source address (possibly overridden), and the (2 byte) type.  See struct ether_header in <netinet/if_ether.c>. Therefore, for Ethernet in particular, it is possible to transmit an arbitrary packet. In the example which follows, rarp_write accepts an arbitrary packet and performs the interface specific manipulations required to transmit that packet. 

The following definitions are taken from <net/nit.h>.

#define NITIFSIZ10/∗ size of ifname in sockaddr ∗/
#define NITBUFSIZ1024/∗ buffers are rounded up to a
∗ multiple of this size (MCLBYTES) ∗/
struct sockaddr_nit {
u_shortsnit_family;
caddr_tsnit_cookie;    /∗ link to filtering ∗/
charsnit_ifname[NITIFSIZ];/∗ interface name (eg, ie0) ∗/
};
 /∗ Header preceeding each packet returned to user ∗/
struct nit_hdr {
intnh_state;/∗ state of tap -- see below ∗/
struct timeval nh_timestamp;/∗ time of arriving packet ∗/
intnh_wirelen;/∗ length (with header) off wire ∗/
union{
intinfo;/∗ generic information ∗/
intdatalen; /∗ length of saved packet portion ∗/
intdropped;/∗ number of dropped matched packets ∗/
intseqno;  /∗ sequence number ∗/
} nh_un;
};
#define nh_infonh_un.info
#define nh_datalennh_un.datalen
#define nh_droppednh_un.dropped
#define nh_seqno  nh_un.seqno
 /∗ Ioctl parameter block ∗/
struct nit_ioc {
intnioc_bufspace;/∗ total buffer space to use ∗/
intnioc_chunksize;/∗ size of chunks to send ∗/
u_intnioc_typetomatch; /∗ magic type with which to match ∗/
intnioc_snaplen;/∗ length of packet portion to snap ∗/
intnioc_bufalign;/∗ packet header alignment multiple ∗/
intnioc_bufoffset;/∗ packet header alignment offset ∗/
struct  timeval nioc_timeout;/∗ delay after packet before drain ∗/
intnioc_flags;  /∗ see below ∗/
};
#define NT_NOTYPES      ((u_int)0)/∗ match no packet types ∗/
#define NT_ALLTYPES     ((u_int)-1)/∗ match all packet types ∗/
 #define NF_PROMISC0x01/∗ enter promiscuous mode ∗/
#define NF_TIMEOUT0x02/∗ timeout value valid ∗/
#define NF_BUSY   0x04/∗ buffer is busy (has data) ∗/
 /∗
 ∗ States for the packet capture portion of nit,
 ∗ some of which are passed to the user.
 ∗/
#define NIT_QUIET0/∗ inactive ∗/
#define NIT_CATCH1/∗ capturing packets ∗/
#define NIT_NOMBUF2/∗ discarding -- out of mbufs ∗/
#define NIT_NOCLUSTER3/∗ discarding -- out of mclusters ∗/
#define NIT_NOSPACE4/∗ discarding -- would exceed bufspace ∗/
/∗ Pseudo-states returned in information packets ∗/
#define NIT_SEQNO5/∗ sequence number of chunk ∗/

To use nit:

 oInclude definitions and declare needed variables, for example

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/nit.h>
#include <net/if.h>
 struct sockaddr_nit snit;
struct nit_ioc nioc;

 oCreate a socket with the call

s = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);

 oBind it to an interface with a code fragment like

snit.snit_family = AF_NIT;
strncpy(snit.snit_ifname, "ie0", sizeof (snit.snit_ifname));
bind(s, (struct sockaddr ∗)&snit, sizeof (snit));

 oTo establish the operating modes, issue an ioctl; for example

bzero(&nioc, sizeof(nioc));
nioc.nioc_bufspace = NITBUFSIZ;
nioc.nioc_chunksize = NITBUFSIZ;
nioc.nioc_typetomatch = NT_ALLTYPES;
nioc.nioc_snaplen = 32767;
nioc.nioc_flags = NF_TIMEOUT;
nioc.nioc_timeout.tv_usec = 200;
if (ioctl(if_fd, SIOCSNIT, &nioc) != 0) {
perror("nit ioctl");
exit(2);
}

 oTo receive packets, issue reads (or recvs). To transmit packets, issue writes (or sends). For example, the following routine will transmit an arbitrary packet (including address information) on the Ethernet. Note that the Ethernet addresses and type are provided in the incoming buffer buf, and must be moved into the sockaddr destination address to satisfy the kernel. 

rarp_write(fd, buf, len)
int fd, len;
char ∗buf;
{
struct sockaddr sa;
int offset = sizeof(sa.sa_data);
int result;
 sa.sa_family = AF_UNSPEC;
bcopy(buf, sa.sa_data, offset);
result = sendto(fd, buf+offset, len-offset,
    0, &sa, sizeof(sa));
return (result+offset);
}

SEE ALSO

bind(2), config(8), ec(4S), ie(4S), if(4N), ioctl(2), read(2V), recv(2), send(2), socket(2), write(2V). 

Network Implementation in Networking on the Sun Workstation.

BUGS

This protocol is provisional, and is subject to change. 

Buffering is limited to 32767 bytes. 

Interface ioctl’s may have different semantics on a nit socket. 

nit is unable to see outgoing transmissions on some interfaces. 

The selection criteria is very simplistic.  Therefore, many packets may be passed to the user program, especially in promiscuous mode. 

Sun Release 3.2  —  Last change: 21 November 1985

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026