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

expression rejects all packets for IPv6 upper-layer protocol #600

Open
yiyuandao opened this issue Aug 23, 2017 · 20 comments
Open

expression rejects all packets for IPv6 upper-layer protocol #600

yiyuandao opened this issue Aug 23, 2017 · 20 comments

Comments

@yiyuandao
Copy link

Hi,

I tried to run following command:

tcpdump -i em1 'ip6 and udp[10]&1 !=0' 

and got the following:

tcpdump: expression rejects all packets

I checked the document pcap-filter.
and in the section 'expr relop expr':

Note that tcp,
udp and other upper-layer protocol types only apply to IPv4, not
IPv6 (this will be fixed in the future)

I wonder is there any plan to add this filter for IPv6?

Thanks.

blazeable pushed a commit to blazeable/libpcap that referenced this issue Sep 3, 2017
For example, on Linux, we add information about memory-mapped capture
support; see comments on GitHub issue the-tcpdump-group#600.
@agnosticdev
Copy link
Contributor

@yiyuandao wanted to follow up on your filtering question for IPv6; You could try using running your UDP filter wide open and then using grep to capture everything coming across as IP6.

tcpdump -i em1 udp and 'udp[10] & 1!=0' -vvv | grep -i 'IP6'

@KimiNewt
Copy link

This issue still exists (in tcp/udp). Is there a reason the syntax ought not to work? Since something like ip6 and tcp port 80 works fine.

If we do want syntax like ip6 and tcp[1] = 0x5 to work, do we want only tcp[1] = 0x5 to look for IPv6 in addition to IPv4? Or leave it as only IPv4?
tcp port 80 Checks for both so there is a little inconsistency.

What is the desired behaviour? I was thinking of making a PR with these changes but I'm not sure what would be preferred.

@infrastation
Copy link
Member

As the pcap-filter(7) man page explains it:

To access data inside the packet, use the following syntax:
proto [ expr : size ]
Note that tcp, udp and other upper-layer protocol types only apply to IPv4, not IPv6 (this will be fixed in the future).

@infrastation
Copy link
Member

Closing as resolved (not a bug, but an improvement that remains to be made).

@bubbasnmp
Copy link

Should this issue be left open to track it as an enhancement request?

@infrastation
Copy link
Member

Alright, let's keep it reopened for a while longer.

@infrastation infrastation reopened this Jun 12, 2022
@jviki
Copy link

jviki commented Jan 31, 2023

Is somebody working on this issue? What is to be implemented? If the compiler can generate instructions to find TCP port after IPv6 header, it should work for anything else inside the TCP header, shouldn't it?

@infrastation
Copy link
Member

This is an old known problem, nobody is working on it now, as far as I am aware. Competent volunteers are welcome to contribute a solution. Ideally it would be best to discuss the solution in sufficient detail before spending time on the code.

@jviki
Copy link

jviki commented Feb 1, 2023

I agree. If it is not too complex, I believe I can provide some development capacity from my team. We would really like this thing to work, however, we have no experience with libpcap internals.

What can be some next step?

@infrastation
Copy link
Member

That might turn out a deeper rabbit hole than it seems because this problem is not to extend an existing dual-stack mapping of another packet data accessor onto UDP, but to introduce dual-stack mapping of packet data accessors for the first time.

In any case, it should be helpful to study this and this documents, then you can have a look at scanner.l, grammar.y and gencode.c and try to think what a good solution would look like. After that it would be a good time to confirm your findings here or on the mailing list before committing into the implementation.

Hopefully that's good enough a starting point.

@jviki
Copy link

jviki commented Feb 1, 2023

@bubbasnmp
Copy link

I think the Wireshark web sites are being reworked. Down link reported on Discord.

@cjmaynard
Copy link

The keynote itself can still be found on YouTube though: https://www.youtube.com/watch?v=XHlqIqPvKw8

@infrastation
Copy link
Member

A copy of the PDF is here.

@infrastation
Copy link
Member

Thank you for raising this, www.tcpdump.org is now using the copy for the documentation reference.

@cjmaynard
Copy link

A possible work-around until a more robust solution is available: ip6 and (ip6[6] = 17) and ((ip6[40 + 8 + 2] & 1) != 0). Of course this only works if there are no IPv6 extension headers present, and I didn't combine the offsets intentionally so it's more obvious that we're skipping the standard 40 bytes of the IPv6 header, the 8 bytes of the UDP header and 2 additional bytes.

@geraldcombs
Copy link
Contributor

I think the Wireshark web sites are being reworked.

They are indeed being reworked, and a recent change inadvertently broke some links. https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf should be working again.

@jviki
Copy link

jviki commented Feb 3, 2023

I did a quick research about the topic and performed some very basic experiments.

Here is bytecode for IPv4/TCP with dst port 80...

$ tcpdump -d 'ip and tcp dst port 80'
Warning: assuming Ethernet
(000) ldh      [12]
(001) jeq      #0x800           jt 2	jf 10
(002) ldb      [23]
(003) jeq      #0x6             jt 4	jf 10
(004) ldh      [20]
(005) jset     #0x1fff          jt 10	jf 6
(006) ldxb     4*([14]&0xf)
(007) ldh      [x + 16]                              ; loading dst port
(008) jeq      #0x50            jt 9	jf 10        ; testing for TCP dst port 80
(009) ret      #262144
(010) ret      #0

Bytecode for IPv4/TCP flags (currently same result as with tcp[tcpflags] & 2 != 0):

$ tcpdump -d 'ip and tcp[tcpflags] & 2 != 0'
Warning: assuming Ethernet
(000) ldh      [12]
(001) jeq      #0x800           jt 2	jf 10
(002) ldb      [23]
(003) jeq      #0x6             jt 4	jf 10
(004) ldh      [20]
(005) jset     #0x1fff          jt 10	jf 6
(006) ldxb     4*([14]&0xf)
(007) ldb      [x + 27]                              ; loading TCP flags
(008) jset     #0x2             jt 9	jf 10        ; testing for TCP flags SYN
(009) ret      #262144
(010) ret      #0

Here is bytecode for IPv6/TCP with dst port 80... It ignores IPv6 extension headers.

$ tcpdump -d 'ip6 and tcp dst port 80'
Warning: assuming Ethernet
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2	jf 7
(002) ldb      [20]
(003) jeq      #0x6             jt 4	jf 7
(004) ldh      [56]                                 ; loading dst port
(005) jeq      #0x50            jt 6	jf 7        ; testing for TCP dst port 80
(006) ret      #262144
(007) ret      #0

And for IPv6/TCP flags, it something like fails:

$ tcpdump -d 'ip6 and tcp[tcpflags] & 2 != 0'
Warning: assuming Ethernet
tcpdump: expression rejects all packets

I do not see any reason why the last expression would not give something like this:

(000) ldh      [12]
(001) jeq      #0x86dd          jt 2	jf 7
(002) ldb      [20]
(003) jeq      #0x6             jt 4	jf 7
(004) ldh      [69]                                 ; loading TCP flags
(005) jset     #0x2             jt 6	jf 7        ; testing for TCP flags SYN
(006) ret      #262144
(007) ret      #0

And expression tcp[tcpflags] & 2 != 0 should take advantage of such improvement as well and consider both IPv4 and IPv6. I think, generating such code would be the goal of this issue. I believe that the logic to be updated is in this switch case: https://github.com/the-tcpdump-group/libpcap/blob/master/gencode.c#L7483.

After that, the much more difficult part would be to parse IPv6 extension headers... But I consider it to be another story.

@jviki
Copy link

jviki commented Feb 3, 2023

Loading of ports is regardless of L3 layer is done via gen_load_a(), the IPv6 case is here https://github.com/the-tcpdump-group/libpcap/blob/master/gencode.c#L1865. Thus, I assume that this logic can be somehow refactored/merged or something.

@infrastation
Copy link
Member

When you study the bytecode, it helps to remember that by default you see the optimized version. You could use BPF Exam to get a slightly better view of what comes out of gencode.c and what how it changes in optimize.c.

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

No branches or pull requests

8 participants