Loading ...
Sorry, an error occurred while loading the content.
 

Re: [hackers-il] help on linux socket filters

Expand Messages
  • Nadav Har'El
    ... 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
    Message 1 of 2 , May 2, 2002
      On Wed, May 01, 2002, praveenjohri wrote about "[hackers-il] help on linux socket filters":
      > 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

      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
      nyh@... |-----------------------------------------
      Phone: +972-53-245868, ICQ 13349191 |Early bird gets the worm, but the second
      http://nadav.harel.org.il |mouse gets the cheese.
    Your message has been successfully submitted and would be delivered to recipients shortly.