link

advertisement
Datalink Access
Datalink Access


Provides access to the datalink layer for an
application
Capabilities


Ability to watch the packets received by the
datalink layer
Run certain programs as applications instead of
kernel. Ex: RARP
Access Methods

3 common methods




BSD Packet Filter (BPF)
SVR4 Datalink Provider Interface (DLPI)
Linux SOCK_PACKET interface
Libpcap library



Publicly available packet capture library
Works with all the above three methods.
Writing programs with this makes them
OS independent
BSD Packet Filter (BPF)

Each datalink driver calls BPF



right before a packet is transmitted
Right after a packet is received
Filter capability



Each application opens BPF device
Can load its own filter
Applied by BPF to each packet

Filter can be as detailed as “only TCP
segments to or from 80, only SYN, FIN or
RST
BSD Packet Filter (BPF)
BSD Packet Filter (BPF)

Three techniques to reduce overhead:



Filters within kernel. Avoids data copy
into user appl.
Only a portion of each packet is copied.
(14+40+20+22=96 bytes)
BPF buffers the data. It is copied to appl
buffer only when full or read timeout
expires.
Datalink Provider Interface (DLPI)
Datalink Provider Interface (DLPI)


Similar to BPF
Differences:


Filter implementation in BPF is 3 to 20 times
faster than DLPI. Directed acyclic control flow
graph an boolean expression tree.
BPF always make the filtering decision before
copying the packet. DLPI may first copy the
packet to pfmod and then make the decision.
Linux

Two methods:


Socket of type:SOCK_PACKET
Socket of family: PF_PACKET


Third argument must specify the frame type.
PF_PACKET:


Type is SOCK_RAW to receive complete link
layer packet.
Socket(PF_PACKET, SOCK_RAW,
htons(ETH_P_ALL));
Linux

Differences with BPF and DLPI:


Provides no kernel buffering. Filtering is
avaialble only with PF_PACKET.
Multiple frames can’t be buffered
together. So it increase no. of sys calls.
libpcap

Provides implementation independent
access to the underlying packet
capture facility.
Libpcap example
int main(int argc, char *argv[])
{
pcap_t *handle;
char *dev;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
char filter_exp[] = "port 23";
bpf_u_int32 mask;
bpf_u_int32 net;
struct pcap_pkthdr header;
const u_char *packet;
/*
/*
/*
/*
/*
/*
/*
/*
/* Session handle */
The device to sniff on */
Error string */
The compiled filter */
The filter expression */
Our netmask */
Our IP */
The header that pcap gives us */
The actual packet */
/* Define the device */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
Libpcap example[1]
/* Find the properties for the device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev,
errbuf);
net = 0;
mask = 0;
}
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", somedev, errbuf);
return(2);
}
/* Compile and apply the filter */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp,
pcap_geterr(handle));
return(2);
}
Libpcap example[2]
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp,
pcap_geterr(handle));
return(2);
}
/* Grab a packet */
packet = pcap_next(handle, &header);
/* Print its length */
printf(“Got a packet with length of [%d]\n", header.len);
/* And close the session */
pcap_close(handle);
return(0);
}
Libpcap example[2]
Download