DRAIN(7P) DRAIN(7P) NAME drain - capture unimplemented link-layer protocols SYNOPSIS #include <sys/types.h> #include <net/raw.h> s = socket(PF_RAW, SOCK_RAW, RAWPROTO_DRAIN); DESCRIPTION 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. EXAMPLES To capture from an Ethernet network interface, first declare an input buffer structure with the required header padding: #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: 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); } DIAGNOSTICS 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. SEE ALSO getsockopt(2), socket(2), intro(3), ethernet(7), raw(7F), snoop(7P) Page 3