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

Problem with MPLS capture filter #408

Closed
svlobanov opened this issue Jan 14, 2015 · 17 comments
Closed

Problem with MPLS capture filter #408

svlobanov opened this issue Jan 14, 2015 · 17 comments

Comments

@svlobanov
Copy link

  1. tcpdump -i eth4 "mpls && port 161" -w public_snmp.pcap --- works ok (captures traffic with 1 mpls label)
  2. tcpdump -i eth4 "mpls && mpls && port 161" -w vpn_snmp.pcap --- also works ok (captures traffic with 2 labels)

tcpdump -i eth4 "(mpls && mpls && port 161) or (mpls && port 161)" -w all_snmp.pcap - captures traffic only with 2 mpls labels. there is no traffic with 1 mpls label in "all_snmp.pcap"

@svlobanov
Copy link
Author

$ aptitude show libpcap0.8
Package: libpcap0.8
Version: 1.5.3-2

$ uname -a
Linux speedtestsrv 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:44 UTC 2014 i686 i686 i686 GNU/Linux

$ cat /etc/issue
Ubuntu 14.04.1 LTS \n \l

@infrastation
Copy link
Member

Could you tell if this reproduces with the latest master build of libpcap?

@svlobanov
Copy link
Author

Problem is reproduced in the latest version of libpcap(git e598f98).

Sample file: https://www.cloudshark.org/captures/e3c2e1feee12

$ /opt/tcpdump/sbin/tcpdump --version
tcpdump version 4.7.0-PRE-GIT_2015_02_04
libpcap version 1.7.0-PRE-GIT_2015_02_04
OpenSSL 0.9.8za 5 Jun 2014

GOOD ---- $ /opt/tcpdump/sbin/tcpdump -r /Users/sergey/mpls-1-2.pcap -n -nn -v -vv -s 0 "(mpls&&mpls&&icmp)"
reading from file /Users/sergey/mpls-1-2.pcap, link-type EN10MB (Ethernet)
00:27:44.753678 MPLS (label 18, exp 0, ttl 255)
(label 16, exp 0, [S], ttl 255)
IP (tos 0x0, ttl 255, id 80, offset 0, flags [none], proto ICMP (1), length 100)
10.31.0.1 > 10.34.0.1: ICMP echo request, id 3941, seq 4768, length 80

GOOD -----$ /opt/tcpdump/sbin/tcpdump -r /Users/sergey/mpls-1-2.pcap -n -nn -v -vv -s 0 "(mpls&&icmp)"
reading from file /Users/sergey/mpls-1-2.pcap, link-type EN10MB (Ethernet)
21:48:57.203902 MPLS (label 29, exp 0, [S], ttl 255)
IP (tos 0x0, ttl 255, id 14, offset 0, flags [none], proto ICMP (1), length 100)
10.1.2.1 > 10.34.0.1: ICMP echo request, id 2621, seq 1579, length 80

BAD ---- $ /opt/tcpdump/sbin/tcpdump -r /Users/sergey/mpls-1-2.pcap -n -nn -v -vv -s 0 "(mpls&&mpls&&icmp) or (mpls&&icmp)"
reading from file /Users/sergey/mpls-1-2.pcap, link-type EN10MB (Ethernet)
00:27:44.753678 MPLS (label 18, exp 0, ttl 255)
(label 16, exp 0, [S], ttl 255)
IP (tos 0x0, ttl 255, id 80, offset 0, flags [none], proto ICMP (1), length 100)
10.31.0.1 > 10.34.0.1: ICMP echo request, id 3941, seq 4768, length 80

P.S. how to upload .pcap file to github issue?

@infrastation
Copy link
Member

Thank you. GitHub issues are currently text-only (GitHub-Markdown-only, to be exact), people typically use xxd, base64 or uuencode (or an equivalent online convertor) to convert a binary file into plain text and paste as a comment.

@svlobanov
Copy link
Author

Thanks for explanations.

"mpls-1-2.pcap" base64-encoded(for history):

1MOyoQIABAAAAAAAAAAAAAAQAAABAAAAGQnAOH4cAwB2AAAAdgAAAAAwlub8OQAwlgUoOIhHAAHR
/0UAAGQADgAA/wGlZgoBAgEKIgABCAA6bwo9BisAAAAAAB8zVKvNq82rzavNq82rzavNq82rzavN
q82rzavNq82rzavNq82rzavNq82rzavNq82rzavNq82rzavNq82rzavNq81QLsA4DoALAHoAAAB6
AAAAADCW5vw5ADCWBSg4iEcAASD/AAEB/0UAAGQAUAAA/wGnBgofAAEKIgABCAC9EQ9lEqAAAAAA
AFOe4KvNq82rzavNq82rzavNq82rzavNq82rzavNq82rzavNq82rzavNq82rzavNq82rzavNq82r
zavNq82rzavNq80=

@guyharris
Copy link
Member

This is, for better or worse, "by-design" or, at least, "not unintended" behavior.

To quote the pcap-filter man page:

   mpls [label_num]
          True if the packet is an MPLS packet.  If [label_num] is  speci-
          fied, only true is the packet has the specified label_num.  Note
          that the first mpls keyword encountered  in  expression  changes
          the  decoding  offsets  for  the  remainder of expression on the
          assumption that the packet is  a  MPLS-encapsulated  IP  packet.
          The  mpls  [label_num] expression may be used more than once, to
          filter on MPLS hierarchies.  Each use of that expression  incre-
          ments the filter offsets by 4.

          For example:
               mpls 100000 && mpls 1024
          filters packets with an outer label of 100000 and an inner label
          of 1024, and
               mpls && mpls 1024 && host 192.9.200.1
          filters packets to or from 192.9.200.1 with an  inner  label  of
          1024 and any outer label.

"Each use of that expression increments the filter offsets by 4." means "once you use it in a filter expression, all filters after it in the filter expression string will check MPLS labels past that label.

This means that in

(mpls && mpls && port 161) or (mpls && port 161)

the first two mpls will cause all subsequent checks to look at the third level of label, so (mpls && port 161) will check for three levels of MPLS filter.

The same applies to vlan.

Arguably, vlan/mpls items should only affect stuff directly ANDed to them; that can probably be implemented, but isn't necessarily simple to implement - it might be easier if, for example, the parser were to build a parse tree and the code generator were to walk the parse tree.

I don't know whether those changes would affect any filters that depend on the current behavior in a useful fashion; I suspect not, as I can't imagine why vlan and mpls should affect stuff ORed with them.

@malaiam
Copy link

malaiam commented Feb 15, 2021

Hi, I'm hitting the same issue with libpcap 1.5.3.
Any plans to get this working somehow, e.g. allow multiple separate filters to be processed at the same time somehow?

@mcr
Copy link
Member

mcr commented Feb 15, 2021

Is that a typo on 1.9.3?

@guyharris
Copy link
Member

This is a general problem with all of the "Each use of this keyword increments the filter offset by..." keywords, such as vlan, mpls, and, as I remember, geneve.

A fix would be a bit complicated, because it means that, in {A} || {B}, any offset-modification by {A} would have to be undone in the evaluation of {B} (unlike {A} && {B}, where the offset-modification by {A} should be in effect when {B} is evaluated). That might require top-down code generation.

@malaiam
Copy link

malaiam commented Feb 16, 2021

Is that a typo on 1.9.3?

Actually no, it's not a typo, it's a vendor installed system where they chose to keep it at that version for whatever reason. I think they use their own implementation to analyse traffic, so it probably doesn't matter for them.

But for tcpdump & libpcap the problem is still actual and without a solution in sight as I see in Guy's reply, even for newest releases.

@malaiam
Copy link

malaiam commented Feb 18, 2021

As a workaround I run several jobs to capture using different filters and then merge the saved files:

# jobs
[1]- Running tcpdump -tnni ens5 -s 0 -w dump_1.pcap mpls and icmp and host 10.10.10.10 &
[2]+ Running tcpdump -tnni ens5 -s 0 -w dump_2.pcap mpls and mpls and icmp and host 10.10.10.10 &
#

@guyharris
Copy link
Member

Duplicate of #798 - "vlan", "pppoe", "mpls", and some other filter tests work the same way.

@cjmaynard
Copy link

cjmaynard commented Oct 29, 2021

  1. tcpdump -i eth4 "mpls && port 161" -w public_snmp.pcap --- works ok (captures traffic with 1 mpls label)
  2. tcpdump -i eth4 "mpls && mpls && port 161" -w vpn_snmp.pcap --- also works ok (captures traffic with 2 labels)

tcpdump -i eth4 "(mpls && mpls && port 161) or (mpls && port 161)" -w all_snmp.pcap - captures traffic only with 2 mpls labels. there is no traffic with 1 mpls label in "all_snmp.pcap"

In this case, wouldn't tcpdump -i eth4 "(mpls && port 161) || (mpls && port 161)" -w all_snmp.pcap have worked?

@cjmaynard
Copy link

As a workaround I run several jobs to capture using different filters and then merge the saved files:

jobs

[1]- Running tcpdump -tnni ens5 -s 0 -w dump_1.pcap mpls and icmp and host 10.10.10.10 &
[2]+ Running tcpdump -tnni ens5 -s 0 -w dump_2.pcap mpls and mpls and icmp and host 10.10.10.10 &

And in this case, wouldn't tcpdump -tnni ens5 -s 0 -w dump.pcap "(mpls and icmp and host 10.10.10.10) || (mpls and icmp and host 10.10.10.10)" have worked?

@tkjaer
Copy link

tkjaer commented Nov 19, 2021

As a workaround I run several jobs to capture using different filters and then merge the saved files:

jobs

[1]- Running tcpdump -tnni ens5 -s 0 -w dump_1.pcap mpls and icmp and host 10.10.10.10 &
[2]+ Running tcpdump -tnni ens5 -s 0 -w dump_2.pcap mpls and mpls and icmp and host 10.10.10.10 &

And in this case, wouldn't tcpdump -tnni ens5 -s 0 -w dump.pcap "(mpls and icmp and host 10.10.10.10) || (mpls and icmp and host 10.10.10.10)" have worked?

It would. This works fine for me when filtering on frames that have either single or double MPLS labels and a specific host:

"(mpls and host 1.2.3.4)" or "(mpls and host 1.2.3.4)"

@malaiam
Copy link

malaiam commented Nov 19, 2021

It works fine for me too with "or", like @cjmaynard proposed, so I'm using that instead of the cumbersome two tcpdumps.
I found that solution somewhere else, but it's good it's also listed here, for the others bumping into the same. Cheers!

@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
Development

No branches or pull requests

7 participants