tcpdump mailing list archives

Re: does "port 25" work?


From: Guy Harris <guy () alum mit edu>
Date: Fri, 1 Aug 2008 01:37:18 -0700


On Jul 31, 2008, at 8:53 PM, U. George wrote:

Guy Harris wrote:
On Jul 31, 2008, at 11:29 AM, U. George wrote:
if i say this:
   tcpdump  -n -v -i eth1

i get a log of: ether type * and port *, ie the PPPoE data.
What you get is a log of "*", i.e. all data.  "port *" is irrelevant;
Not so. The log of "*" is the sum of all the "*"'s. which "port *" is a part of. Optimization suggests that all "*"'s are true, and need not be tested.

*ENTIRELY* so!  If you say

        tcpdump -n -v -i eth1

the generated filter program, even *WITHOUT* optimization, does no tests:

        $ tcpdump -d -O -i en1
        (000) ret      #96

because it was not *ASKED* to do any tests! It's not as if libpcap generates a whole bunch of wildcard tests and then optimizes them away.

not all packets that would match "ether type *" *HAVE* a port number.
Not terribly relevant. expression will always be false ( ie port domain will never match anything from those ethertypes ) .

It would be true that "port domain" will never match anything from those ethertypes only if it actually *checks* the ethertype. The code generated for "port domain" for an Ethernet, with an IPv6-enabled libpcap, is:

        $ tcpdump -d -i en0 port domain
        (000) ldh      [12]
(001) jeq #0x86dd jt 2 jf 10 # check for an Ethernet type of IPv6

        # IPv6:

        (002) ldb      [20]
(003) jeq #0x84 jt 6 jf 4 # check for an IPv6 "next header" of SCTP

        # Not SCTP:

(004) jeq #0x6 jt 6 jf 5 # check for an IPv6 "next header" of TCP

        # Not TCP:

(005) jeq #0x11 jt 6 jf 23 # check for an IPv6 "next header" of UDP

        # SCTP, TCP, or UDP atop IPv6:

        (006) ldh      [54]
(007) jeq #0x35 jt 22 jf 8 # check for an SCTP, TCP, or UDP source port of 53

        # source port not 53:

        (008) ldh      [56]
(009) jeq #0x35 jt 22 jf 23 # check for an SCTP, TCP, or UDP destination port of 53

        # not IPv6:

(010) jeq #0x800 jt 11 jf 23 # check for an Ethernet type of IPv4

        # IPv4:

        (011) ldb      [23]
(012) jeq #0x84 jt 15 jf 13 # check for an IPv4 protocol type of SCTP

        # Not SCTP:

(013) jeq #0x6 jt 15 jf 14 # check for an IPv4 protocol type of TCP

        # Not TCP:

(014) jeq #0x11 jt 15 jf 23 # check for an IPv4 protocol type of UDP

        # SCTP, TCP, or UDP atop IPv4:

        (015) ldh      [20]
(016) jset #0x1fff jt 23 jf 17 # check whether this packet is a fragment after the first fragment

# Not a fragment after the first fragment, i.e. first fragment or only fragment:

        (017) ldxb     4*([14]&0xf)                 # get the IPv4 header length
        (018) ldh      [x + 14]
(019) jeq #0x35 jt 22 jf 20 # check for an SCTP, TCP, or UDP source port of 53

        # source port not 53:

        (020) ldh      [x + 16]
(021) jeq #0x35 jt 22 jf 23 # check for an SCTP, TCP, or UDP destination port of 53

        # IPv6 or IPv4; SCTP, TCP, or UDP; source or destination port 53
        (022) ret      #96

# either not IPv6 nor IPv4, or (IPv6 or IPv4) but not SCTP nor TCP nor UDP, or (SCTP or TCP or UDP) but not
        # to or from port 53
        (023) ret      #0

Note, first of all, that the checks for the source and destination ports check a different location in the packet depending on whether the packet is IPv6 or IPv4; therefore, you *CANNOT*, in an IPv6- enabled libpcap, check the port number without, at *MINIMUM*, checking the Ethernet type.

Furthermore, there are protocols other than SCTP, TCP, and UDP that run atop IP, so, before it checks the port number, it first needs to check the protocol type/next header field, so that it doesn't just look at some random location in the packet that might happen to have a 2-byte big-endian value of 53 in it.

"port domain" is equivalent to "tcp port domain or udp port domain", which is equivalent to "(tcp or udp) and "(tcp port domain or udp port domain)", which is equivalent to "ip and (tcp or udp) and (tcp port domain or udp port domain)". For better or worse, "ip" on Ethernet is equivalent to "ether type ip", so "port domain" is equivalent to "ether type ip and (tcp or udp) and (tcp port domain or udp port domain)".

Without a detailed study, on my part, I am unable to jump to that conclusion. Specifying port does not necessarily also specify ether type ( or anything else ).

That's OK, as a libpcap developer I know how the code generator works, so I've done the detailed study for you; that is a correct conclusion, as that's how the code generator works - just checking for IP doesn't, for better or worse, check for VLAN-encapsulated or PPPoE-encapsulated IP packets.

That doesn't mean it *shouldn't* check for them; it just means that it currently *doesn't*. (Note, of course, that checking for them involves checking Ethernet types....) I don't know how much work would be involved in making it generate code to check for them;.
-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.


Current thread: