[comp.unix.ultrix] Help with "programming" packet filter

taku@cathedral.cerc.wvu.wvnet.edu (Takumei So) (05/08/91)

     I am trying to "program" the packet filter available on ultrix
machines so that it will accept only packets whose the destination
ethernet address is 8:0:2b:17:b3:a0.

     It's not working, however (read() returns 0 bytes), and I would
like someone to point out what I'm doing wrong.  I have reasons to 
suspect I'm not setting the filter up correctly.

     The following is the code for filter that I adapted from the man
page with some modifications.  What am I doning wrong here?

>struct enfilter Filter =
>{
>   36, 12,
>   ENF_PUSHWORD + 0,
>   ENF_PUSHLIT, 0x0008, /* 0x0800 */
>   ENF_CAND,
>   ENF_PUSHWORD + 1,
>   ENF_PUSHLIT, 0x172b, /* 0x2b17 */
>   ENF_CAND,
>   ENF_PUSHWORD + 2,
>   ENF_PUSHLIT, 0xa0b3, /* 0xb3a0 */
>   ENF_EQ
>};

    Specifically, am I setting up the byte order correctly?  And
is the filter command list length set corectly (I set it to 12
shortwords)?

     man page for packetfilter gives the following example:

>          struct enfilter f =
>          {
>              36, 0,                /* priority and length */
>              ENF_PUSHWORD + 6,
>              ENF_PUSHLIT, 0x3580,
>              ENF_CAND,             /* Ethernet type == 0x8035 (RARP) */
>              ENF_PUSHWORD + 10,
>              ENF_PUSHLIT, 0x0300,
>              ENF_CAND,             /* reverse request type = 0003 */
>              ENF_PUSHWORD + 0,
>              ENF_PUSHLIT, 0xFFFF,
>              ENF_CAND,             /* dest addr = FF-FF */
>              ENF_PUSHWORD + 1,
>              ENF_PUSHLIT, 0xFFFF,
>              ENF_CAND,             /* dest addr = FF-FF */
>              ENF_PUSHWORD + 2,
>              ENF_PUSHLIT, 0xFFFF,
>              ENF_EQ                /* dest addr = FF-FF */
>          };

    This example "first checks the Ethernet type of the packet.  If it
is not a RARP packet, it is discarded.  Then, the RARP type field is
checked for a reverse request (type 3), followed by a check for a
broadcast destination address."

    In this example, I don't understand why packet length is set to 0.
Could it be a mistake in man page?

    The machine I'm using is a ultrix machine, DECstation 5000 running
ULTRIX V4.0 Rev.179.  I'm running it as su, and the interface is set to
promiscuous mode.

    Any help, or example codes for using packetfilter, will be greatly 
appreciated!!!

-Taku

Taku So    
taku@cerc.wvu.wvnet.edu
Concurrent Engineering Research Center
Morgantown, WV  26505

mjr@hussar.dco.dec.com (Marcus J. Ranum) (05/08/91)

taku@cathedral.cerc.wvu.wvnet.edu (Takumei So) writes:

>    The machine I'm using is a ultrix machine, DECstation 5000 running
>ULTRIX V4.0 Rev.179.  I'm running it as su, and the interface is set to
>promiscuous mode.
>    Any help, or example codes for using packetfilter, will be greatly 
>appreciated!!!

	I think 4.2 comes with the packet screen daemon - which is a table
driven packet filterer - very useful for screened IP gateways. I don't know
if the source to it is something that can be given out or not. I'll defer
to the author.

mjr.

mogul@pa.dec.com (Jeffrey Mogul) (05/09/91)

[This is a longish response to a long message, but I thought other
people might find it interesting.]

In article <1712@babcock.cerc.wvu.wvnet.edu> taku@cathedral.cerc.wvu.wvnet.edu (Takumei So) writes:
>
>     I am trying to "program" the packet filter available on ultrix
>machines so that it will accept only packets whose the destination
>ethernet address is 8:0:2b:17:b3:a0.
>
>     It's not working, however (read() returns 0 bytes), and I would
>like someone to point out what I'm doing wrong.  I have reasons to 
>suspect I'm not setting the filter up correctly.

Is 8:0:2b:17:b3:a0 the address of the machine on which you are running
your packet filter application?  If not, you must first put the interface
into promiscuous mode, or else your host will never see packets for that
address.  (Also, due to some bad judgement on my part, until Ultrix 4.2,
if you ARE running the program on 8:0:2b:17:b3:a0, it will not
see IP, ARP, DECnet, or LAT packets to/from that ethernet address.  Sorry!)

>    The machine I'm using is a ultrix machine, DECstation 5000 running
>ULTRIX V4.0 Rev.179.  I'm running it as su, and the interface is set to
>promiscuous mode.

Are you sure?

A packet filter application can request that the interface be put into
promiscuous mode by using a code sequence such as:

        enmode |= ENPROMISC;
        if (ioctl(if_fd, EIOCMBIS, &enmode) < 0) {
                perror(device);
                exit(-1);
        }

where if_fd is the file descriptor for the packet filter file.  However,
this will have NO EFFECT unless the super-user has first given the
command
	/usr/etc/pfconfig +p -a
since booting.  (I simply put this command into /etc/rc.local; it has no
effect unless a promiscuous-mode packet filter application is running.
Or rather: on Ultrix 4.0 and 4.2, it has no effect.  In Ultrix 4.1,
there is some sort of bug that makes LAT not work, so don't do it
if you run LAT on Ultrix 4.1.)  Remember, runnig pfconfig +p is NOT
sufficient; the application must also set the ENPROMISC mode bit.
This little dance is the way it is so that the interface is in promiscuous
mode only when an application wants it to be so.

If you want to do a simple test, instead of adding this code to your
application, you can live dangerously:
	/etc/ifconfig ln0 promisc
When you are done, you should turn it off with
	/etc/ifconfig ln0 -promisc
unless you want your system to waste its time throwing away packets.

>     The following is the code for filter that I adapted from the man
>page with some modifications.  What am I doning wrong here?
>
>>struct enfilter Filter =
>>{
>>   36, 12,
>>   ENF_PUSHWORD + 0,
>>   ENF_PUSHLIT, 0x0008, /* 0x0800 */
>>   ENF_CAND,
>>   ENF_PUSHWORD + 1,
>>   ENF_PUSHLIT, 0x172b, /* 0x2b17 */
>>   ENF_CAND,
>>   ENF_PUSHWORD + 2,
>>   ENF_PUSHLIT, 0xa0b3, /* 0xb3a0 */
>>   ENF_EQ
>>};
>
>    Specifically, am I setting up the byte order correctly?  And
>is the filter command list length set corectly (I set it to 12
>shortwords)?

I can't see anything wrong with your code.  The byte order and
filter length look right.  This why I'm guessing that you haven't
got the promiscuous-mode business right.

Just for the sake of completeness, I should point out that there
is a slightly more efficient way to write the same filter:

struct enfilter Filter =
{
   36, 9,
   ENF_PUSHWORD + 0,
   ENF_PUSHLIT|ENF_CAND, 0x0008, /* 0x0800 */
   ENF_PUSHWORD + 1,
   ENF_PUSHLIT|ENF_CAND, 0x172b, /* 0x2b17 */
   ENF_PUSHWORD + 2,
   ENF_PUSHLIT|ENF_CAND, 0xa0b3 /* 0xb3a0 */
};

The last ENF_CAND can almost certainly be ENF_EQ, but I've tested
this example only the way it is written here.

>     man page for packetfilter gives the following example:
>
>>          struct enfilter f =
>>          {
>>              36, 0,                /* priority and length */
>>              ENF_PUSHWORD + 6,
>>              ENF_PUSHLIT, 0x3580,
>>              ENF_CAND,             /* Ethernet type == 0x8035 (RARP) */
>>              ENF_PUSHWORD + 10,
>>              ENF_PUSHLIT, 0x0300,
>>              ENF_CAND,             /* reverse request type = 0003 */
>>              ENF_PUSHWORD + 0,
>>              ENF_PUSHLIT, 0xFFFF,
>>              ENF_CAND,             /* dest addr = FF-FF */
>>              ENF_PUSHWORD + 1,
>>              ENF_PUSHLIT, 0xFFFF,
>>              ENF_CAND,             /* dest addr = FF-FF */
>>              ENF_PUSHWORD + 2,
>>              ENF_PUSHLIT, 0xFFFF,
>>              ENF_EQ                /* dest addr = FF-FF */
>>          };
>
>    This example "first checks the Ethernet type of the packet.  If it
>is not a RARP packet, it is discarded.  Then, the RARP type field is
>checked for a reverse request (type 3), followed by a check for a
>broadcast destination address."
>
>    In this example, I don't understand why packet length is set to 0.
>Could it be a mistake in man page?

Ooops.  Yes, the length is certainly wrong.  I'm afraid this is almost
certainly my fault; I think I wrote this example.  And, obviously,
didn't test it!

By the way, about 5 years ago I wrote a little "compiler" to take
a simple expression language and create "optimized" packet filters.
It's in Modula-2, so it isn't much use to most people.  If someone
would be interested in reimplementing it in a more convenient language,
for public-domain use, I'll send you my Modula-2 sources and provide
some help.

-Jeff