Ethereal-dev: Re: [Fwd: Re: [Ethereal-dev] Filter expressions for exclusion]

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxx>
Date: Wed, 1 Jan 2003 18:08:59 -0800
On Wed, Jan 01, 2003 at 08:29:47AM -0600, Esh, Andrew wrote:
> While what you say is technically true, it does not address John McDermott's
> point.

It wasn't intended to.  It was intended to note, as a side comment, that
checking the tcp.port field isn't the best way to check for HTTP traffic.

> I have a question about "!http". If the rule is: "Referring to a protocol
> implies that the packets match that protocol before they are tested.", then
> "!http" would always filter out ALL packets. If they aren't HTTP, they get
> filtered out because "http" is undefined. If they are HTTP they are tested,
> and filtered out because of the NOT operator. Is that really the case, or is
> there another special case for the http field? What other fields work this
> way, and what other fields work the tcp.port way? (I don't need a listing, I
> just need the question considered.)

The way display filter primitive expressions work is:

	a protocol tree contains instances of fields, including, for
	each instance in a tree of a protocol, an instance for that
	protocol and, for each non-protocol field, an instance for each
	time that field appears in a packet;

	a primitive expression with no comparison operator evaluates to
	"true" if an instance of that field appears in the protocol tree
	and "false" otherwise;

	a primitive expression with a comparison operator evaluates to
	"true" if an instance of that field appears in the protocol tree
	and the comparison operation, with the value supplied and the
	value for that instance, evaluates to "true", and "false"
	otherwise.

Boolean operators, such as "not", "and", and "or", apply to the values
of primitive expressions.

There is no idea of "matching a protocol"; "http" is just a field, just
as "tcp.srcport" is a field, and "tcp.port" is a field, and the display
filter language does not have any special notion that the presence of
the protocol for a field is tested before the field itself is tested.

I.e., the rule is *NOT*, for *ANY* field, "referring to a protocol
implies that the packets match that protocol before they are tested". 

There are also no special cases for any fields.  "ip", "tcp", "ipv6",
"http", "ip.proto", "ip.src", "ip.dst", "ip.addr", "ip.checksum",
"tcp.ack", "tcp.len", "tcp.srcport", "tcp.dstport", "tcp.port",
"tcp.checksum", and so on are all treated the same.

"!http" is a combination of the Boolean "not" operator and the primitive
expression "http".  "http" evaluates to "true" if there is any instance
of the field "http" in the packet, and "false" otherwise, therefore
"!http" evaluates to "false" if there is any instance of the field
"http" in the packet and "true" otherwise.  That field happens to be
present in the protocol tree if the HTTP dissector put it there because
there was HTTP in the packet, and is not present otherwise.

"tcp.port == 80" is a primitive expression; it evaluates to "true" if
there is an instance of the "tcp.port" field in the packet and it has
the value 80, and "false" otherwise.  That field happens to be present
in the protocol tree if the TCP dissector put it there because there was
a TCP source or destination port number in the packet - it puts an
instance in there for the TCP source port number and another instance
for the TCP destination port number - and is not present otherwise.

"tcp.port != 80" is a primitive expression; it evaluates to "true" if
there is an instance of the "tcp.port" field in the packet and it does
not have the value 80, and "false" otherwise.

"!(tcp.port == 80)" is a combination of the Boolean "not" operator and
the primitive expression "tcp.port == 80".  "tcp.port == 80" evaluates
to "true" in the cases described two paragraphs earlier, so "!(tcp.port
== 80)" evaluates to "false" if there is an instance of the "tcp.port"
field in the packet and it has the value 80, and "true" otherwise - or,
to reverse that, it evaluates to "true" if there is *no* instance of the
"tcp.port" field in the packet with the value 80, regardless of whether
that's because there is no instance at all or if all instances have
values other than 80 - and "false" otherwise.