Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter on IP field does not work when MPLS is present. #1070

Closed
edgar-costa opened this issue Nov 25, 2021 · 5 comments
Closed

Filter on IP field does not work when MPLS is present. #1070

edgar-costa opened this issue Nov 25, 2021 · 5 comments

Comments

@edgar-costa
Copy link

Version:

tcpdump version 4.9.3
libpcap version 1.8.1
OpenSSL 1.1.1 11 Sep 2018

I have experienced some weird behaviour when trying to match to IP tos field, when MPLS is present. To show you what happens, I am simply pinging between two nodes, the ping goes encapsulated over mpls, while the reply has no mpls. For all the experiments I am sending one single ping (request and reply).

sudo tcpdump -n  -i POR-eth2 -vv
tcpdump: listening on POR-eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
01:25:49.817640 MPLS (label 1 (router alert), exp 0, [S], ttl 62)
        IP (tos 0x0, ttl 64, id 32764, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.15.1 > 10.0.2.1: ICMP echo request, id 2323, seq 1, length 64
01:25:49.834338 IP (tos 0x0, ttl 61, id 42664, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.2.1 > 10.0.15.1: ICMP echo reply, id 2323, seq 1, length 64

So far, so good. And as you can see, for both packets it parses the IP tos field. However, I want to only capture packets with some specific tos field, thus I use the filter ip[1]==tos. However, when doing so, mpls packets are not displayed, only the IP ping reply.

sudo tcpdump -n  -i POR-eth2 -vv ip[1]==0
tcpdump: listening on POR-eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
01:27:52.422301 IP (tos 0x0, ttl 61, id 64249, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.2.1 > 10.0.15.1: ICMP echo reply, id 2630, seq 1, length 64

Ok, I thought I need to extend the filter to have mpls && ip[1]==0 or ip[1]==0. So if i try that... for some reason I am only getting the mpls packet, why?

sudo tcpdump -n  -i POR-eth2 -vv "(mpls && ip[1]==0) or ip[1]==0"
tcpdump: listening on POR-eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
01:30:37.420896 MPLS (label 1 (router alert), exp 0, [S], ttl 62)
        IP (tos 0x0, ttl 64, id 57604, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.15.1 > 10.0.2.1: ICMP echo request, id 3046, seq 1, length 64

However, if I if keep the same filter, but I reverse the logical expression it does work, like why?? I am missing something, is this a bug? See below:

sudo tcpdump -n  -i POR-eth2 -vv "ip[1]==0 or (mpls && ip[1]==0)"
tcpdump: listening on POR-eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
01:32:13.875259 MPLS (label 1 (router alert), exp 0, [S], ttl 62)
        IP (tos 0x0, ttl 64, id 65009, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.15.1 > 10.0.2.1: ICMP echo request, id 3286, seq 1, length 64
01:32:13.891797 IP (tos 0x0, ttl 61, id 48789, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.2.1 > 10.0.15.1: ICMP echo reply, id 3286, seq 1, length 64

Is there any difference between the last two expressions? I could not find anything in the documentation.

Thanks!

@infrastation
Copy link
Member

This looks very much like a duplicate of #408 (and subsequently #798). Perhaps it would be a good next FAQ entry.

@edgar-costa
Copy link
Author

edgar-costa commented Nov 25, 2021

Hi Denis,

And thanks for the reply. I am not sure I understood it properly even after reading those other issues and mpls option. If I understood properly, every time you use the keyword mpls you move the offset 4 bytes. This might be important when you want to inspect inner mpls labels, but thats not even my case. I believe what I want to do is simpler. I just want to check if IP tos field == some number.

So I still have the following questions?

  1. Why does not my first expression work? ip[1] ==0 ? This should work when there is only ethernet + IP, but also when there is ethernet + mpls labels + IP, no? tcpdump should parse till IP.

  2. Does it mean that with the filter I used: ip[1]==0 or (mpls && ip[1]==0)this will only work if I have either, normal IP packets or, packets with only 1 mpls label and then IP. If so, how can I do it for 1 mpls label or any number of them??? I am a bit lost.

Thanks a lot!

Edit: Could it be that to do what i want I have to do :

"ip[1]==0 or (mpls && ip[1]==0) or (mpls && ip[1]==0) or (mpls && ip[1]==0) or (mpls && ip[1]==0) or (mpls && ip[1]==0) or (mpls && ip[1]==0)"

This will either do normal IP packets, or 1 label, 2, 3, 4, 5, 6, etc...? Isnt there a way to do this simpler?

@infrastation
Copy link
Member

If you want to understand the filters, the pcap-filter man page would be the first reference material (that said, if you spot a valid place for improvement there, please contribute it).

  1. As far as I understand it, ip[1] == 0 is a shorthand for ip and ip[1] == 0 or ether proto \ip and ip[1] == 0, which does not match Ethernet MPLS packets because IPv4 and MPLS use different EtherType values. Which makes sense because applying bare IPv4 offset to an MPLS packet will read from incorrect address.
  2. Yes, that's correct. Each subsequent mpls keyword looks one more label down the MPLS stack (I do not know if that will fail safe when the stack is not deep enough). I am not aware of an immediate simpler way to do that,; potentially it may be implementable using the same approach as the protochain keyword, which only works for userspace filtering.

This might make more sense if you consider that pcap filters work in libpcap, often in the OS kernel, and the packet decoding you see works in tcpdump, in a mostly independent manner. That is, what tcpdump knows about MPLS label stack and the data before and after it does not depend on what libpcap knows about MPLS label stack and the data before and after it.

@infrastation
Copy link
Member

This issue seems to be addressed. Would anybody like to add anything before closing?

@guyharris guyharris transferred this issue from the-tcpdump-group/tcpdump Nov 26, 2021
@infrastation
Copy link
Member

For posterity, there is now a FAQ entry about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants