Subject: help on linux socket filters

From: "praveenjohri" <[email-masked]>
Date: Wed, 01 May 2002 23:21:35 +0530

hi everybody,

i am new to this group and seek help on lsf.......

1)can anybody tell me where to find in detail how to write filter i.e.the syntax or the

filter language for lsf .the bpf man page is not helping me much 'coz i am not good 

with assembly and there is some difference between lsf and bpf also and the examples are not veryrich in details.

2) now i am getting filter code from tcpdump since it deaplays the user grammer to filter code translation to the screen...but in this case i every time have to recompile 

whenever i will attach anew filter....i want to make this process more dynamic like

tcpdump itself so that i dont have to recompile it everytime...please do not suggest to read tcpdump source code since i am not getting it much as i am a newbie to

this area...but with some focused feedback i can try this...

somebody help me i have deadline approaching

with regards

praveen johri
Get Your Private, Free E-mail from Indiatimes at  http://email.indiatimes.com
Buy Music, Video, CD-ROM, Audio-Books and Music Accessories from http://www.planetm.co.in

---

From: "Nadav Har'El" <[email-masked]>
Date: Thu, 2 May 2002 14:21:48 +0300

> filter language for lsf .the bpf man page is not helping me much 'coz i am not good 

NOTE: this list is not a Linux list. The only reason I'm answering is because
I have a good answer which I think other people might find useful.

There's a good article on bpf (Berkeley Packet Filter) from Berkeley that
I can send you if you're interested.
However, the easier approach is to have the libpcap library compile for
you a tcpdump(8)-like phrase into a BPF automaton.

Here is an example code I wrote. linux_filtered_ip_socket() returns a file
descriptor of a socket filtered with the given filter. For example,

	linux_filtered_ip_socket("tcp[13] & 4 == 4")

returns a socket which gets only RST (TCP reset) packets.
Please read the code below for comments about how this works, and about
the differences in different libpcap versions.

extern "C" {
#include <net/bpf.h>
#include <pcap.h>
}
// Linux_filtered_ip_socket opens a socket that recieves every packet
// that matches some given criterion (currently a filter string that is
// defined like in tcpdump(8), only that we restrict ourselves to IP packets).
// The socket file-descriptor is returned, or <0 on failure (e.g., if the
// current kernel does not support socket filtering).
//
// Note that the way we do this "packet-capturing" is very Linux-specific,
// though similar tricks may be available for other systems supporting BPF
// (Berkeley Packet Filter) style interfaces.
//
// Important design consideration:
// The fact that we have a socket, a real file-descriptor, rather then some
// procedural interface like in libpcap (see pcap(3)) allows a single thread
// to select(2) input from this or another socket (libpcap's interface doesn't
// seem to allow multiplex packet capturing with input from other sources).

linux_filtered_ip_socket(/* const */ char *filter_string)
{
    // We open a packet socket (see packet(7)), not a raw socket (see
    // raw(7)) because raw sockets are given packets after firewalling is
    // done, and we want to be passed even firewalled packets.
    // packet(7) // says that "Packet sockets are not subject to the input
    // or output firewall chains." (raw(7) sockets are, from my
    // experimentation).
    // We still ask for "cooked" (SOCK_DGRAM) IP packets, without the link
    // level (e.g., Ethernet) headers.

    //int fd=socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    int fd=socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
    if(fd<0){
        cerr << "can't open raw input socket: " << strerror(errno) <<"\n";
        return LSF_ERROR_SOCKET;
    }
    // We're not going to write to this socket, so we might as well close
    // the writing side...
    shutdown(fd,SHUT_WR);

    // Attach the filter:
    // TODO: Currently, for simplicity, I use libpcap's function that
    // converts a tcpdump(8)-like filter string into a full-fledged BPF
    // virtual-machine-code filter.
    // We're "abusing" libpcap, by making it compile a filter program for us,
    // without really using the rest of its packet-capturing services.
    // pcap_compile_nopcap() was meant for exactly this use, but it has
    // very serious problems: it's only available in the newest versions
    // (not the common 0.4 version), it has no way of showing the reasons
    // for an error, and it doesn't work properly for me. Libpcap's split
    // development means that these issues won't be resolved soon (even if I
    // send patches), so I need to use an ugly workaround to use the standard
    // pcap_compile. WARNING: UGLY CODE AHEAD!

    // we hope tmpbuffer can hold a struct pcap (pcap_t), but because we
    // don't have pcap-int.h to include, we can't get the actual size (the
    // actual definition of pcap_t is not specified in the pcap include
    // file...), or the field order in the structure... this is UGLY, not
    // portable and and dangerous...
    int tmpbuffer[(1000+PCAP_ERRBUF_SIZE)/sizeof(int)];
    bzero(tmpbuffer, sizeof(tmpbuffer));
    tmpbuffer[0] = -1; /* pc->fd */
    tmpbuffer[1] = 0xffff; /* pc->snapshot */
    tmpbuffer[2] = DLT_RAW; /* pc->linktype */
    pcap_t *pc= (pcap_t *)tmpbuffer;

    struct bpf_program bp;
    if (pcap_compile(pc, &bp, filter_string, 1, 0xffffffff)) {
        close(fd);
        pcap_perror(pc, "linux_filtered_ip_socket");
        return LSF_ERROR_FILTERSTRING;
    }
    if(setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bp, sizeof(bp))<0){
        close(fd);
        cerr << "can't set socket filter: " << strerror(errno) <<"\n";
        //throw Exception_LSF();
        return LSF_ERROR_FILTER;
    }

    return fd;
}

-- 
Nadav Har'El                        |      Thursday, May 2 2002, 20 Iyyar 5762
[email-masked]             |-----------------------------------------
Phone: +972-53-245868, ICQ 13349191 |Early bird gets the worm, but the second
http://nadav.harel.org.il           |mouse gets the cheese.