DRAIN(7P) DRAIN(7P)
drain - capture unimplemented link-layer protocols
#include <sys/types.h>
#include <net/raw.h>
s = socket(PF_RAW, SOCK_RAW, RAWPROTO_DRAIN);
The Drain protocol provides non-promiscuous capture of packets having
unimplemented link-layer protocol types, i.e., packets that the operating
system normally receives and drops ``down the drain''. It treats packets
as datagrams containing a link-layer header followed by data. Drain uses
the Raw address format, interpreting ports as link-layer type codes (in
host byte order) to match against unimplemented types in received
packets. Multiple sockets may bind to the same port on a network
interface.
Drain can map several link-layer type codes to a port. There is one
type-to-port mapping for each network interface; it is initialized to map
zero to zero. Call ioctl(2) with the SIOCDRAINMAP command and the
address of the following structure, declared in <net/raw.h>, to set a
mapping:
struct drainmap {
u_short dm_minport; /* lowest port in range */
u_short dm_maxport; /* and highest port */
u_short dm_toport; /* port mapped by range */
};
Drain input from Ethernet network interfaces is demultiplexed based on
the ether_type member of the ether_header structure, declared in
<netinet/if_ether.h> and documented in ethernet(7).
If the link-layer header size is not congruent with RAW_ALIGNGRAIN, Drain
input prepends RAW_HDRPAD(hdrsize) bytes of padding to received packets.
Output on a Drain socket, using write(2) or send(2), takes a buffer
address pointing at the link-layer packet to be transmitted, not at any
prepended padding.
To capture from an Ethernet network interface, first declare an input
buffer structure with the required header padding:
Page 1
DRAIN(7P) DRAIN(7P)
#include <sys/types.h>
#include <net/raw.h>
#include <netinet/if_ether.h>
#define ETHERHDRPAD RAW_HDRPAD(sizeof(struct ether_header))
struct etherpacket {
char pad[ETHERHDRPAD];
struct ether_header ether;
char data[ETHERMTU];
};
To capture all Reverse ARP (RARP) packets, create a Drain socket and bind
it to the RARP port on the primary network interface (error handling is
omitted for clarity):
#define ETHERTYPE_RARP 0x8035
int s;
struct sockaddr_raw sr;
s = socket(PF_RAW, SOCK_RAW, RAWPROTO_DRAIN);
sr.sr_family = AF_RAW;
sr.sr_port = ETHERTYPE_RARP;
bzero(sr.sr_ifname, sizeof sr.sr_ifname);
bind(s, &sr, sizeof sr);
Alternatively, to capture all Ethernet packets with IEEE 802.3
encapsulations, create and bind a socket to a port different from any
valid ether_type:
#define IEEE802_3PORT 1
int s;
struct sockaddr_raw sr;
s = socket(PF_RAW, SOCK_RAW, RAWPROTO_DRAIN);
sr.sr_family = AF_RAW;
sr.sr_port = IEEE802_3PORT;
bzero(sr.sr_ifname, sizeof sr.sr_ifname);
bind(s, &sr, sizeof sr);
Map all Ethernet types corresponding to packet lengths, as specified by
802.3, to the bound port:
Page 2
DRAIN(7P) DRAIN(7P)
struct drainmap map;
map.dm_minport = 1;
map.dm_maxport = 1500;
map.dm_toport = IEEE802_3PORT;
ioctl(s, SIOCDRAINMAP, &map);
Before reading, it may be desirable to increase the Drain socket's
default receive buffer size. The following code also shows how to
transmit a link-layer packet:
struct etherpacket ep;
int cc = 10000;
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &cc, sizeof cc);
for (;;) {
cc = read(s, (char *) &ep, sizeof ep);
/* . . . */
write(s, (char *) &ep.ether, cc - sizeof ep.pad);
}
A socket operation may fail with one of the following errors returned:
[EISCONN] when trying to establish a connection on a socket which
already has one, or when trying to send a datagram with
the destination address specified and the socket is
already connected;
[ENOBUFS] when the system runs out of memory for an internal data
structure or a send or receive buffer.
[EADDRINUSE] when an attempt is made to create a socket with a port
which has already been allocated;
[EADDRNOTAVAIL]
when an attempt is made to create a socket with a network
address for which no network interface exists.
[EOPNOTSUPP] when an ioctl operation not supported by the Drain
protocol is attempted.
getsockopt(2), socket(2), intro(3), ethernet(7), raw(7F), snoop(7P)
PPPPaaaaggggeeee 3333 [ Back ]
|