[Galaxy S II Original Android Development] sam3000:
RE: http://review.cyanogenmod.com/#/c/18475/ screen off packet filters

RE: http://review.cyanogenmod.com/#/c/18475/

I think I'm making some progress with decoding the filter format:

<id> <negate match 0|1> <filter type> <offset> <mask> <value>

ID - unique filter id. It looks possible that different ranges have different effects but more research is needed.

If negate match field is 0, normal processing is applied. If 1, the sense of the test is reversed (rather than the accept/drop action itself).

Filter type 0 seems to be match from the beginning of the ethernet frame. Haven't tested for any other types.

Offset is the number of bytes into the frame to begin checking the mask/value.

Mask identifies the bits of interest.

Value is what the bits of interest must be set to.

Mask and value must be the same length.

The default filters (ie pre patch) are:

100 0 0 0 0x010000000000000000000000000020 0x000000000000000000000000000000

104 0 0 0 0xFFFFFF 0x01005E

Processing logic seems to be accept on any match (where accept means the packet is permitted to the host stack when the screen is off).

So the above rules are:

id 100:

bits of interest are the first bit of the first byte of the dest eth address and the value must be 0. ie must be unicast

14 bytes further in we get to the IP header. the first nibble is the IP protocol version and the second bit must be zero which means it will never match ipv6 traffic.

summary: permit any unicast non-ipv6 traffic

id 104:

much simpler - match any frames with a dest mac 01005E, ie standard multicast frames.

Both of above decodes seem match tcpdump testing - multicast is permitted and wakes the phone, any unicast is also permitted but broadcast traffic is not.

Some of the comments in the code do not match the direction of the logic so either things have changed or the language is simply incorrect. For example, one of the filters referenced but not used in kernel/samsung/smdk4210/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c is:

/* discard NAT Keepalive packets */

102 0 0 36 0xffffffff 0x11940009

This would mean skip past the eth and IP headers (14+20 bytes) and then go two bytes into the layer 4 header. We're matching on the following 8 bytes so, in practice this is likely to be UDP (if this were TCP it would cover the sequence number) and corresponds to the destination port (0x1194 = 4500 IPSEC NAT traversal) and udp datagram size field in bytes. The udp header is 8 bytes so this implies the packet must have a 1 byte of udp payload. So, certainly, it looks like it's matching NAT keepalives but, contrary to the comment, it would permit them not discard them.

=================================

The filter logic enables some interesting concepts like you could permit unicast udp, tcp and arp only with:

100 0 0 0 0x0100000000000000000000000000200000000000000000ff 0x000000000000000000000000000000000000000000000006

101 0 0 0 0x0100000000000000000000000000200000000000000000ff 0x000000000000000000000000000000000000000000000011

102 0 0 0 0x010000000000000000000000ffff 0x0000000000000000000000000806

I've verified this actually works (and it does :-). It would break IPSEC but it's interesting nonetheless..

In short, the best general purpose filter right now is probably: accept any non-IPv6 unicast.

ie

100 0 0 0 0x010000000000000000000000000020 0x000000000000000000000000000000