About
Community
Bad Ideas
Drugs
Ego
Erotica
Fringe
Society
Technology
Hack
Introduction to Hacking
Hack Attack
Hacker Zines
Hacking LANs, WANs, Networks, & Outdials
Magnetic Stripes and Other Data Formats
Software Cracking
Understanding the Internet
Legalities of Hacking
Word Lists
register | bbs | search | rss | faq | about
meet up | add to del.icio.us | digg it

Info on /dev/nit


NOTICE: TO ALL CONCERNED Certain text files and messages contained on this site deal with activities and devices which would be in violation of various Federal, State, and local laws if actually carried out or constructed. The webmasters of this site do not advocate the breaking of any law. Our text files and message bases are for informational purposes only. We recommend that you contact your local law enforcement officials before undertaking any project based upon any information obtained from this or any other web site. We do not guarantee that any of the information contained on this system is correct, workable, or factual. We are not responsible for, nor do we assume any liability for, damages resulting from the use of any information on this site.

The Network Interface Tap

by

Idefix

To enable access to the raw network-link layer SunOs offers the Network
Interface Tap (NIT(4P)). NIT consists of a streams device driver (streamio(4)),
nit_if(4M), and two streams modules. One module for filtering, nit_pf(4M), and
one module for buffering, nit_buf(4M). The modules provide a general
functionality and can be used for other streams than the NIT.

A general setup for NIT is opening the device associated with nit_if,
/dev/nit. The resulting stream can be configured with a number of ioctls.
Depending on the need, one or both of the modules can be pushed on top of the
nit_if. Before using the stream for reading and writing it has to be bound to a
physical network interface. From this moment on it is possible to read and
write raw packets on the network. Depending on the promiscous flag all
packets are read or only the packets destined for the interface are read.
Writing consists of supplying the destination ethernet address and data making
up the rest of the packet.

Next a more detailed description of setting up the nit device and configuring
the modules follows. First opening the nit device is shown with an overview
of the different options. Next the working of the nit_pf packetfilter is
described with an example of filtering a single tcp connection between two
machines. After the packetfilter the nit_buf module is shown with its
different configuration options. To conclude the way to write to the nit
device is presented with a simple example of writing a bogus packet.

1. The nit device
=================

The first step in setting up the nit is opening the device /dev/nit with
open(2). With ioctls the resulting stream can now be configured according to
the needs. The ioctls can be divided into general stream ioctls and specific
nit ioctls. The only stream ioctl that is needed to get a workable situation
is I_SRDOPT with parameter RMSGD. This sets the read(2) mode to reading of
messages in discard mode, which means that data is read from the stream on
message boundaries for the number of bytes requested. All bytes remaining of
the message are discared. Default is bitstream which is continuous, and
another option is without discard leaving the remaining bytes for the next
read. This one and others can be found in streamio(4).
The most relevant ioctls that apply to the nit_if are:

NIOCBIND The nit_if needs to be bound to a physical ethernet device
A list of available device can be obtained with the SIOCGIFCONF
ioctl (if(4N)). The parameter should be in the form of
'struct ifreq' (if(4N)).

NIOCSNAP This option allows packets to be trimmed to a snapshot length
and so reducing the total amount of space needed to store
received packets. The ethernet header will always be copied
and a zero length snapshot means copying complete packets.

NIOCSFLAGS Set flags for the promiscous state and nit_if effecting which
headers will be added to the packet. The flag parameter is a
long of which the bits denote the following flags:

NI_PROMISC set the promiscous mode to read all packets.
Only allowed for the superuser.

NI_TIMESTAMP add a header consisting of a 'struct timeval'

NI_DROPS add a header consisting of a 'u_long' with
packets dropped sofar by nit_if

NI_LEN add a header consisting of a 'u_long' with
the original length of the packet before it
was cut to the snapshot length.

The headers are prepended to the received packet in the order
as used above.

The ioctls can be issued in two ways. One way is directly, the other way is
^^^^^ (IS THIS ALWAYS SO???)
through the I_STR stream ioctl. The I_STR ioctl can send ioctls down a stream
to other modules in that stream and has an option to time out. I will use the
latter.

As a result the following piece of code emerges, of which a similar copy can
be found in the manpage nit(4P).

-----------------------------------------------
Nit setup code without buffer and filter module
-----------------------------------------------

int nitif_fd;
struct strioctl si;
struct ifreq ifr;
unsigned long snaplen;
unsigned long flags;
char *interface;

nitif_fd = open("/dev/nit", O_RDWR);

/* Set read messages to discard */
ioctl(nitif_fd, I_SRDOPT, (char *)RMSGD);

/*** The packet filter setup code can be placed here ***/

/*** The buffer module setup code can be placed here ***/

/* Copy the interface name to the name field of the ifrec struct */
strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';

/* set the ioctl timeout infinite */
si.ic_timout = INFTIM;

/* Bind the stream to the interface */
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (void *)𝔦
if (ioctl(nitif_fd, I_STR, (void *)&si) < 0)
{
fprintf(stderr,"nit: NIOCBIND\n");
close(nitif_fd);
exit(1);
}

/* Set the snaplength to snaplen */
si.ic_cmd = NIOCSSNAP;
si.ic_len = sizeof(snaplen);
si.ic_dp = (void *)&snaplen;
if (ioctl(nitif_fd, I_STR, (void *)&si) < 0)
{
fprintf(stderr,"nit: NIOCSSNAP\n");
close(nitif_fd);
exit(1);
}

/* Set the flags for the nit device */
si.ic_cmd = NIOCSFLAGS;
si.ic_len = sizeof(flags);
si.ic_dp = (void *)&flags;
if (ioctl(nitif_fd, I_STR, (void *)&si) < 0)
{
fprintf(stderr,"nit: NIOCSFLAGS\n");
close(nitif_fd);
exit(1);
}

/* Flush anything in the queue at this moment */
if (ioctl(nitif_fd, I_FLUSH, (void *)FLUSHR) < 0)
{
fprintf(stderr,"nit: I_FLUSH\n");
close(nitif_fd);
exit(1);
}

--------------------------------------

After this code it's possible to read packets from the network with read(2) a
packet at the time. Again code comparable to that from manpage nit(4P) can be
used:

---------------------------
Reading from the nit stream
---------------------------

while ((cc = read(if_fd, buf, MAXBUF)) >= 0) {
register u_char *cp = buf;
struct timeval *tvp = NULL;
u_long drops = 0;
u_long pktlen;
struct ether_header *eth;
struct ip *iph;

if (flags&NI_TIMESTAMP) {
struct nit_iftime *ntp;

ntp = (struct nit_iftime *)cp;
cp += sizeof *ntp;
tvp = &ntp->nh_timestamp;
}

if (flags&NI_DROPS) {
struct nit_ifdrops *ndp;

ndp = (struct nit_ifdrops *)cp;
cp += sizeof *ndp;
drops = ndp->nh_drops;
}

if (flags&NI_LEN) {
struct nit_iflen *nlp;

nlp = (struct nit_iflen *)cp;
cp += sizeof *nlp;
pktlen = nlp->nh_pktlen;
}

eth = (struct ether_header *) cp;
cp += sizeof( struct ether_header );

iph = (struct ip *) cp;
cp += iph->hl*4;

/* etc proceeding to process the packet */

}

--------------------------------------

To limit time nescessary to process the packets two mechanisms are provided.
One is filtering the other is buffering. Filtering limits the packets that
are passed down the stream. The buffer limits the syscalls that need to be
made to read the packets. Next the packet filter module is described.

2. The packet filter module
===========================

If the packet filter is used, it is pushed immediately on top of the opened
stream with the I_PUSH ioctl. After the push the filter can be configured
with the NIOCSETF ioctl. This ioctl has as parameter a pointer to a
'struct packetfilt', which contains in turn a list of filter commands.
The filter command list is an array of u_shorts which consists of operators
and data. The commands operate on a stack on which, besides push, also binary
operations can be performed. The maximumlength of the list is 40 shorts.

The commands can be divided in three groups. The first has to do with pushing
data on the stack. The commands are:

ENF_PUSHLIT push the following shortword in the list on the
stack.
ENF_PUSHZERO push zero on the stack.
ENF_PUSHWORD+n push the n-th shortword of the packet on the
stack.
ENF_NOPUSH don't push anything.

In every shortword a push command (except for ENF_PUSHWORD) can be combined
with a command of the second or third group. The second group consists of
binary operatores, which operate on the top two elements of the stack. The two
elements are replaced with the result of the operation. The following
operations are possible:

ENF_EQ equal
ENF_NEQ not equal
ENF_LT less then
ENF_LE less then or equal
ENF_GT greater then
ENF_GE greater then or equal
ENF_AND binary AND
ENF_OR binary OR
ENF_XOR binary XOR
ENF_NOP no operation

The result is zero for a false result and non-zero for a true result.
To increase the filters effectiveness a third group of operators exists.
These cause the packetfilter to terminate prematurely. For instance this is
an advantage when subsequent checks would be irrelevant if a check turned
out false. The commands are:

ENF_COR keep packet if equal else continue
ENF_CAND reject packet if not equal else continue
ENF_CNOR reject packet if equal else continue
ENF_CNAND keep packet if not equal else continue

With these commands now a filter can be built. Because the commands occupy
different bitfields of the shortword the | operation can be used to combine
push and binary operators.
Next follow two examples. The first filters all udp packets destined for the
dns port, the second all packets between a host pair and port pair.

------------------------------------
Setting up for the DNS packet filter
------------------------------------

if (ioctl(nitif_fd, I_PUSH, "pf") < 0)
{
fprintf(stderr,"nit: 'pf' push failed\n");
close(nitif_fd);
exit(1);
}

pf.Pf_Priority = 0;
ptr = pf.Pf_Filter;
*ptr++ = ENF_PUSHWORD + 6; /* ethertype at 6th shortword */
*ptr++ = ENF_PUSHLIT|ENF_CAND; /* push the next short and then */
*ptr++ = htons(ETHERTYPE_IP); /* do the ENF_CAND */
*ptr++ = ENF_PUSHWORD + 11; /* ip_proto at 11th shortword */
*ptr++ = ENF_PUSHLIT|ENF_AND; /* cut off ttl field */
*ptr++ = 0xff;
*ptr++ = ENF_PUSHLIT|ENF_CAND; /* push udp type i17 and reject */
*ptr++ = 17; /* if not equal */
*ptr++ = ENF_PUSHWORD + 18; /* udpport at 18th shortword */
*ptr++ = ENF_PUSHLIT|ENF_CAND;
*ptr++ = 53; /* dns port number */

/* if no elements remain on the stack or the stack top is non zero */
/* then the packet is accepted. A zero value or an error condition */
/* leads to rejection */

pf.Pf_FilterLen = ptr - &pf.Pf_Filter[0];

if(ioctl(fd, NIOCSETF,&pf) == -1)
{
fprintf(stderr,"nit: set filter failed\n");
close(nitif_fd);
exit(1);
}

--------------------------------------

--------------------------------------------------
Setting up the filter for TCP connection filtering
--------------------------------------------------

if (ioctl(nitif_fd, I_PUSH, "pf") < 0)
{
fprintf(stderr,"nit: 'pf' push failed\n");
close(nitif_fd);
exit(1);
}

pf.Pf_Priority = 0;
ptr = pf.Pf_Filter;
*ptr++ = ENF_PUSHWORD + 6; /* ethertype at 6th shortword */
*ptr++ = ENF_PUSHLIT|ENF_CAND; /* push the next short and then */
*ptr++ = htons(ETHERTYPE_IP); /* do the ENF_CAND */
*ptr++ = ENF_PUSHWORD + 11; /* ip_proto at 11th shortword */
*ptr++ = ENF_PUSHLIT|ENF_AND; /* cut off ttl field */
*ptr++ = 0xff;
*ptr++ = ENF_PUSHLIT|ENF_CAND; /* push tcp type 6 and reject */
*ptr++ = 6; /* if not equeal */

*ptr++ = ENF_PUSHWORD + 17; /* tcp src port 17th shortword */
*ptr++ = ENF_PUSHLIT|ENF_EQ; /* compare to port */
*ptr++ = port;
*ptr++ = ENF_PUSHWORD + 18; /* tcp dst port 18th shortword */
*ptr++ = ENF_PUSHLIT|ENF_EQ;
*ptr++ = port;
*ptr++ = ENF_CREQ; /* reject if results are equal */
/* thus both not equal to port */
/* or both equal which should */
/* not happen */

*ptr++ = ENF_PUSHWORD + 13; /* msw of src ip address */
*ptr++ = ENF_PUSHLIT|ENF_EQ;
*ptr++ = hostaddr->msw;
*ptr++ = ENF_PUSHWORD + 14; /* lsw of src ip address */
*ptr++ = ENF_PUSHLIT|ENF_EQ;
*ptr++ = hostaddr->lsw;
*ptr++ = ENF_AND; /* AND results of src EQs */

*ptr++ = ENF_PUSHWORD + 15; /* msw of dst ip address */
*ptr++ = ENF_PUSHLIT|ENF_EQ;
*ptr++ = hostaddr->msw;
*ptr++ = ENF_PUSHWORD + 16; /* lsw of dst ip address */
*ptr++ = ENF_PUSHLIT|ENF_EQ;
*ptr++ = hostaddr->lsw;
*ptr++ = ENF_AND; /* AND results of dst EQs */
*ptr++ = ENF_OR; /* accept if one AND produces a */
/* non-zero. happens if both EQ */
/* are true */

pf.Pf_FilterLen = ptr - &pf.Pf_Filter[0];

if(ioctl(fd, NIOCSETF,&pf) == -1)
{
fprintf(stderr,"nit: set filter failed\n");
close(nitif_fd);
exit(1);
}

--------------------------------------

3. The buffering module
=======================

To minimize time taken by the systems packet processing, a buffering module
is available. This module collects all packets in a chunk. When the total
length of the chunk would exceed the chunksize, the chunk is passed on. The
new packet is then placed in a new chunk. If the packet is longer than the
chunksize, one oversized chunk is passed on. Another reason for the buffer
module to pass on a chunk is when a timeout period expires. When no packet
arrived within the timeout period a zero length chunk is passed on.

On every packet that is placed in a chunk, the buffer module prepends a
header with the actual packet length and the total length to the next packet
in the chunk. With this information it's possible to easily process every
packet in the chunk.

The buffer module is also configured with ioctls just like with the packet
filter. As described, the two configurable options of a buffer module are the
chunksize and the timeout period. For this purpose the following ioctls are
most relevant:

NIOCSTIME Set the timeout period to the value in the parameter of
'struct timeval'. NOTE: a value of 0 also sets the chunksize
to zero, thus effectivly disableing the buffer.

NIOCSCHUNK Set the chunksize to the value of the 'unsigned int' parameter

NIOCCTIME Clear the timeout period, setting it to infinity.

A typical way to configure the buffer module with these ioctls and the way to
process the chunks produced by the module are both shown in the following two
pieces of code.

----------------------------
Setting up the buffer module
----------------------------

/* set the ioctl timeout infinite */
si.ic_timout = INFTIM;

/* Set the timeout period */
si.ic_cmd = NIOCSTIME;
si.ic_len = sizeof(timeout);
si.ic_dp = (void *)&timeout;
if (ioctl(nitif_fd, I_STR, (void *)&si) < 0)
{
fprintf(stderr,"nit: NIOCSTIME\n");
close(nitif_fd);
exit(1);
}

/* set the chunksize */
si.ic_cmd = NIOCSCHUNK;
si.ic_len = sizeof(chunksize);
si.ic_dp = (void *)&chunksize;
if (ioctl(nitif_fd, I_STR, (void *)&si) < 0)
{
fprintf(stderr,"nit: NIOCSCHUNK\n");
close(nitif_fd);
exit(1);
}

----------------------------

----------------------------------
Processing of buffer module chunks
----------------------------------

int nr;
char buf[CHUNKSIZE];

while((nr = read(nitif_fd, buf, CHUNKSIZE)) >= 0){
char *bp = buf;
char *bufend = buf+nr;

while(bp < bufend){
register char *cp = bp;
struct nit_bufhdr *bufhdrp;
unsigned long pktlen;

/* get the buffer packet header and point to packet start */
bufhdrp = (struct nit_bufhdr *)cp;
cp += sizeof(struct nit_bufhdr);

/* Use the information from the header prepended by nit_buf */
pktlen = bufhdrp->msglen;
bp += bufhdrp->nhb_totlen;

/* process the packet, including other headers from nit */
process(cp, pktlen);

}
}

---------------------------

4. Writing packets
===================

Except for the various ways of reading packets from the nit stream, all
modules also pass packets to the write side of the interface. They are passed
along without modification by both the packet filter and the buffer module.
Writing takes place through the putmsg(2) call. This call takes as parameters
the filedescriptor of the stream, a control block and a data block. The data
consists of the complete packet excluding the link-level (==ethernet-)
header. The control block consists of a 'struct sockaddr'. The .sa_family
field of this struct must be AF_UNSPEC and the .sa_data field must equal the
link-level header of the data block. The source ethernet address can be
ommitted as the ethernet card fills that field. The fourth parameter of the
putmsg call is a flag field, which is concerned with block or non-blocking and
is taken 0 here (block if write queue is full). The ethernet header is defined
by the following 'struct ether_header' :

struct ether_header {
unsigned char ether_dhost[6];
unsigned char ether_shost[6];
unsigned short ether_type;
}

An ethernet address consists of 6 bytes. Most ethernet cards have a fixed
ethernet address (I know depca cards (DEC) let you modify it), which is placed
in the source field when the packet is send.

To send a packet using this low-level interface means that beside a
destination IP address also a destination ethernet address is required.
Normally the network code looks for this ethernet address using the routing
table or using ARP (Address Resolution Protocol). The ethernet address
supplied as destination should always be on the net your machine is connected
to. When the destination IP is on another net you should use the ethernet
address of the router for that IP domain. Normally using the default router as
destination will work fine. You can lookup information concerning routers with
the 'netstat -r' command. This gives a list of domains and IP addresses and
their assosciated routers. The default can be found on the entry line with
'default'. To find the ethernet of this machine the 'arp hostname' command
can be used. When there is no entry yet, then first do a 'ping hostname' to
get the entry in the arp cache.
Another possibillity is when hosts have forwarding turned on. This is generally
the case with Sun boxes, I don't know about other systems. When you send a
packet to such a machine with a destination IP address of a different machine,
it will be forwarded using the routing info on the host that you send it to by
ethernet address.

Sending packets can be achieved by the following code.

------------------------------
Code to send packets using Nit
------------------------------

#include <netinet/if_ether.h>
#include <sys/stropts.h>
#include <sys/socket.h>

char *packet; /* data to send (without eth hdr) */
unsigned long pktlen; /* size of data packet */
char ethdst[6]; /* 6 byte ethernet destination */
struct sockaddr sa;
struct strbuf ctl, data;
struct ether_header *eth;

sa.sa_family = AF_UNSPEC;

/* Fill in the control block with the link-level header */
/* Source ethernet address is filled in by the card */

eth = (struct ether_header *) &sa.sa_data;
bcopy (ethdst, ð->ether_dhost, sizeof( eth->ether_dhost ));
eth->type = ETHERTYPE_IP;

ctl.maxlen = ctl.len = sizeof(sa);
ctl.buf = (char *)&sa;

data.maxlen = data.len = pktlen;
data.buf = (caddr_t) packet;

/* Send it off ... */

if (putmsg(nitif_fd, &ctl, &data, 0) < 0)
{
fprintf(stderr,"nit: putmsg\n");
close(nitif_fd);
exit(1);
}

------------------------

rholans:~$ X-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-X
Another file downloaded from: & the Temple of the Screaming Electron
NIRVANAnet(tm) HQ (510) 935-5845
! \ AREA CODE WILL BE (925) AS OF 03/98
-$- -------- *
! . / Raw Data for Raw Nerves
/_\ /-o-\ Information * Innuendo * Lies
(o..) | * Full access for first-time callers
+ |:| /^\ /~\ Thousands of text files * Multi-line Chat
! |:|/\ _| |____|:| We don't want to know who you are, where you
/^\ / O |/...\ /_-_\ live, or what your phone number is
|@ \_| @ /:::::|/|- : -| We are not Big Brother
| | | /~ |/| _ |
|____|/~ @ /~\ |/|_(_)_| Free Speech * Anonymous Access * User-Supported
/_______|_|_|/ To make a $10 donation call (900)443-4227 x145
X-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-X
 
To the best of our knowledge, the text on this page may be freely reproduced and distributed.
If you have any questions about this, please check out our Copyright Policy.

 

totse.com certificate signatures
 
 
About | Advertise | Bad Ideas | Community | Contact Us | Copyright Policy | Drugs | Ego | Erotica
FAQ | Fringe | Link to totse.com | Search | Society | Submissions | Technology
Hot Topics
Php
Withstanding an EMP
Good computer destroyer?
Wow, I never thought the navy would be so obvious.
Alternatives Internets to HTTP
Anti-Virus
a way to monitor someones AIM conversation
VERY simple question: browser history
 
Sponsored Links
 
Ads presented by the
AdBrite Ad Network

 

TSHIRT HELL T-SHIRTS