* [RFC] BPF program access to transport header
@ 2010-04-30 19:39 Paul LeoNerd Evans
2010-04-30 20:15 ` Patrick McHardy
0 siblings, 1 reply; 3+ messages in thread
From: Paul LeoNerd Evans @ 2010-04-30 19:39 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 1816 bytes --]
Via the SKF_NET_OFF extension area, a BPF program has nice easy access
to the network header, wherever it might happen to be in the packet.
This makes it simpler to write filters on e.g. IPv4 headers, knowing
that fields will always be at simple offsets relative to SKF_NET_OFF.
Using the data at WORD[SKF_AD_PROTO] it's easy also to find out what
network protocol this is.
I would like to provide similar for the transport header. Without doing
so, it is very hard to parse e.g. UDP or TCP headers that may be
contained within IPv6 protocol, because of the linked-list way IPv6
headers chain on to each other. BPF doesn't provide a while() loop or
any kind of backward jump, meaning the filter program has to be
loop-unrolled a static number of times. This quickly leads to very large
programs.
I forsee a number of issues with trying to provide this:
* How to provide the protocol number (e.g. 6 for TCP, 1 for ICMP) to
the BPF program
* How to obtain the transport offset - AIUI, the skf_transport_offset()
won't actually be set yet by the time the filter program runs.
* What to do if the underlying protocol doesn't support a transport
layer above it - e.g. ARP.
Ideally, this would make it easy to filter, say, TCP destination port
80, by doing the following:
LD WORD[SKF_AD_PROTO]
JEQ ETHERTYPE_IPV4, 1, fail
JEQ ETHERTYPE_IPv6, 0, fail
LD WORD[SKF_AD_TRANSPROTO]
JEQ IPPROTO_TCP, 0, fail
LD WORD[SKF_TRANS_OFF+0]
JEQ 80, 0, fail
LD len
RET A
fail:
RET 0
In this short simple BPF program we've avoided all the issues involved
with trying to parse IPv6 headers.
Can we make this work?
--
Paul "LeoNerd" Evans
leonerd@leonerd.org.uk
ICQ# 4135350 | Registered Linux# 179460
http://www.leonerd.org.uk/
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC] BPF program access to transport header
2010-04-30 19:39 [RFC] BPF program access to transport header Paul LeoNerd Evans
@ 2010-04-30 20:15 ` Patrick McHardy
2010-04-30 22:10 ` Paul LeoNerd Evans
0 siblings, 1 reply; 3+ messages in thread
From: Patrick McHardy @ 2010-04-30 20:15 UTC (permalink / raw)
To: Paul LeoNerd Evans; +Cc: netdev
Paul LeoNerd Evans wrote:
> Via the SKF_NET_OFF extension area, a BPF program has nice easy access
> to the network header, wherever it might happen to be in the packet.
> This makes it simpler to write filters on e.g. IPv4 headers, knowing
> that fields will always be at simple offsets relative to SKF_NET_OFF.
> Using the data at WORD[SKF_AD_PROTO] it's easy also to find out what
> network protocol this is.
>
> I would like to provide similar for the transport header. Without doing
> so, it is very hard to parse e.g. UDP or TCP headers that may be
> contained within IPv6 protocol, because of the linked-list way IPv6
> headers chain on to each other. BPF doesn't provide a while() loop or
> any kind of backward jump, meaning the filter program has to be
> loop-unrolled a static number of times. This quickly leads to very large
> programs.
>
> I forsee a number of issues with trying to provide this:
>
> * How to provide the protocol number (e.g. 6 for TCP, 1 for ICMP) to
> the BPF program
Using one of the registers?
> * How to obtain the transport offset - AIUI, the skf_transport_offset()
> won't actually be set yet by the time the filter program runs.
For IPv4 its trivial. For IPv6 you could use ipv6_skip_exthdr().
A slightly more flexible way would be to use something like the
netfilter ipv6_find_hdr() function to get the offset of any header
type. The protocol number could be returned in one of the registers
(the other one would contain the offset).
> * What to do if the underlying protocol doesn't support a transport
> layer above it - e.g. ARP.
I'd say simply abort the filter.
> Ideally, this would make it easy to filter, say, TCP destination port
> 80, by doing the following:
>
> LD WORD[SKF_AD_PROTO]
> JEQ ETHERTYPE_IPV4, 1, fail
> JEQ ETHERTYPE_IPv6, 0, fail
>
> LD WORD[SKF_AD_TRANSPROTO]
> JEQ IPPROTO_TCP, 0, fail
>
> LD WORD[SKF_TRANS_OFF+0]
> JEQ 80, 0, fail
>
> LD len
> RET A
>
> fail:
> RET 0
>
> In this short simple BPF program we've avoided all the issues involved
> with trying to parse IPv6 headers.
>
> Can we make this work?
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC] BPF program access to transport header
2010-04-30 20:15 ` Patrick McHardy
@ 2010-04-30 22:10 ` Paul LeoNerd Evans
0 siblings, 0 replies; 3+ messages in thread
From: Paul LeoNerd Evans @ 2010-04-30 22:10 UTC (permalink / raw)
To: Patrick McHardy, netdev
[-- Attachment #1: Type: text/plain, Size: 2044 bytes --]
On Fri, Apr 30, 2010 at 10:15:09PM +0200, Patrick McHardy wrote:
> > I forsee a number of issues with trying to provide this:
> >
> > * How to provide the protocol number (e.g. 6 for TCP, 1 for ICMP) to
> > the BPF program
>
> Using one of the registers?
Using, how? What operation would put the numbers in there in the first
place?
I was thinking more of simply providing an ancilliary data area field,
similar to SKF_AD_PROTO and SKF_AD_HATYPE, following along the same
idea.
LD WORD[SKF_AD_TRANSPROTO]
would then load the A register with the transport protocol number.
> > * How to obtain the transport offset - AIUI, the skf_transport_offset()
> > won't actually be set yet by the time the filter program runs.
>
> For IPv4 its trivial. For IPv6 you could use ipv6_skip_exthdr().
> A slightly more flexible way would be to use something like the
> netfilter ipv6_find_hdr() function to get the offset of any header
> type. The protocol number could be returned in one of the registers
> (the other one would contain the offset).
I sortof meant in general. I really don't think trying to add
IPv4/IPv6-specific code into net/core/filter.c is going to go down well.
On the other hand, I observe from casual experimentation, that on
receipt of a TCP packet in IPv4 over ethernet, the offets are:
mac=0 network=14 transport=14
This suggests more work needing to be done somewhere, because I'd expect
for an Ethernet/IPv4/TCP packet to get
mac=0 network=14 transport=34
> > * What to do if the underlying protocol doesn't support a transport
> > layer above it - e.g. ARP.
>
> I'd say simply abort the filter.
That sounds reasonable.
Another question occurs:
* How to obtain the transport protocol number? I can easily provide it
in the AD area; say as SKF_AD_TRANSPROTO; but how can
net/core/filter.c know the value?
--
Paul "LeoNerd" Evans
leonerd@leonerd.org.uk
ICQ# 4135350 | Registered Linux# 179460
http://www.leonerd.org.uk/
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-04-30 22:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-30 19:39 [RFC] BPF program access to transport header Paul LeoNerd Evans
2010-04-30 20:15 ` Patrick McHardy
2010-04-30 22:10 ` Paul LeoNerd Evans
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).