BIOCSSEESENT ioctl on 5.1 ...

Matthew Grooms mgrooms at shrew.net
Tue Jul 1 08:34:10 PDT 2003


Question,

     Is there somthing magic about setting this flag? I wrote a small program
( built on 5.1 ) that uses the bpf to read broadcast packets off a local
private network, forward them to a peer ( over IPSEC ) who in turn drops them
onto its private network ( and visa-versa ). To prevent looping, I was hoping
to set the BIOCSSEESENT flag on the fd. Unfortunately, when this option is
set I no longer receive any packets on the interface. Here is the relevent
code.

        // open the berkley packet filter device

        int32_t hbpf;
        int32_t mnum = 0;
        char device[ 25 ];
        do
        {
                sprintf( device,"/dev/bpf%d", mnum );
                mnum++;
                hbpf = open( device, O_RDWR );
        }
        while( hbpf < 0 && errno == EBUSY );

        if( hbpf == -1 )
        {
                printf( "failed to open a packet filter device\n" );
                printf( "exiting ...\n" );
                return -1;
        }

        printf( "using filter device '%s'\n", device );

        // assign the filter to a network device

        struct ifreq ifr;
        strcpy( ifr.ifr_name, config.get_service_iface() );
        if( ioctl( hbpf, BIOCSETIF, ( uint32_t ) &ifr ) == -1 )
        {
                printf( "unable to assign filter to network device
\'%s\'\n",
ifr.ifr_name );
                printf( "exiting ..." );
                return -1;
        }

        printf( "using network device \'%s\'\n", ifr.ifr_name );

        // dont buffer packet data

        uint32_t value = 1;
        if( ioctl( hbpf, BIOCIMMEDIATE, &value ) == -1 )
        {
                printf( "unable to set BIOCIMMEDIATE option for filter
device\n" );
                printf( "exiting ...\n" );
                return -1;
        }

        // use promiscuous mode

        if( ioctl( hbpf, BIOCPROMISC, &value ) == -1 )
        {
                printf( "unable to set BIOCPROMISC option for filter
device\n" );
                printf( "exiting ...\n" );
                return -1;
        }

        // use non-blocking io

        if( ioctl( hbpf, FIONBIO, &value ) == -1 )
        {
                printf( "unable to set FIONBIO option for filter device\n"
);
                printf( "exiting ...\n" );
                return -1;
        } // disable header complete mode

        if( ioctl( hbpf, BIOCSHDRCMPLT, &value ) == -1 )
        {
                printf( "unable to set BIOCGHDRCMPLT option for filter
device\n" );
                printf( "exiting ...\n" );
                return -1;
        }

        // don't return localy generated packets

        value = 0;
        if( ioctl( hbpf, BIOCSSEESENT, &value ) == -1 )
        {
                printf( "unable to set BIOCGSEESENT option for filter
device\n" );
                printf( "exiting ...\n" );
                return -1;
        }

        // get the filter buffer size

        int32_t buff_size;
        if( ioctl( hbpf, BIOCGBLEN, &buff_size ) == -1 )
        {
                printf( "unable to obtain filter buffer size\n" );
                printf( "exiting ...\n" );
                return -1;
        }

        // setup our bpf filter machine data

        uint32_t ins_count = 8;
        uint32_t ins_index = 0;

        struct bpf_insn * insns = new struct bpf_insn[ ins_count ];
        if( !insns )
        {
                printf( "unable to alloc filter macine data\n" );
                printf( "exiting ...\n" );
                return -1;
        } insns[ ins_index ].code = BPF_LD+BPF_H+BPF_ABS; //
load data ( half word )
        insns[ ins_index ].k = 12; // offset (
protocol )
        ins_index++;

        insns[ ins_index ].code = BPF_JMP+BPF_JEQ+BPF_K; // cmp
equality and jmp
        insns[ ins_index ].jt = 0; // true
offset
        insns[ ins_index ].jf = 5; // false
offset
        insns[ ins_index ].k = 0x0800; // value
        ins_index++;

        insns[ ins_index ].code = BPF_LD+BPF_B+BPF_ABS; // load data
( byte )
        insns[ ins_index ].k = 23; // offset (
transport type )
        ins_index++;

        insns[ ins_index ].code = BPF_JMP+BPF_JEQ+BPF_K; // cmp
equality and jmp
        insns[ ins_index ].jt = 0; // true
offset
        insns[ ins_index ].jf = 3; // false
offset
        insns[ ins_index ].k = 0x11; // value
        ins_index++;

        /*
         * TODO : check for a matching port
         */

        insns[ ins_index ].code = BPF_LD+BPF_W+BPF_ABS; // load data
( word )
        insns[ ins_index ].k = 30; // offset (
destination addre
        ins_index++;

        insns[ ins_index ].code = BPF_JMP+BPF_JEQ+BPF_K; // cmp
equality and jmp
        insns[ ins_index ].jt = 0; // true
offset
        insns[ ins_index ].jf = 1; // false
offset
        insns[ ins_index ].k = 0xffffffff; // value
        ins_index++;

        insns[ ins_index ].code = BPF_RET+BPF_K; // return (
passed )
        insns[ ins_index ].k = ( u_int ) -1; // accept
byte count ( everyt
        ins_index++;

        insns[ ins_index ].code = BPF_RET+BPF_K; // return (
failed )
        insns[ ins_index ].jt = 0; //
        insns[ ins_index ].jf = 0; //
        insns[ ins_index ].k = 0; // accept
byte count ( ignore
        ins_index++;

        // assign the bpf filter program

        struct bpf_program bpfp;
        bpfp.bf_insns = insns;
        bpfp.bf_len = ins_count;

        if( ioctl( hbpf, BIOCSETF, &bpfp ) == -1 )
        {
                printf( "unable to set filter program\n" );
                printf( "exiting ...\n" );
                return -1;
        }

PS ... From what I can tell, I am following the bpf manpage to the tee and
think there could be possibly an issue with this on 5.1. Could anyone help
please. Thanks in advance ...

-Matthew


More information about the freebsd-current mailing list