Eric Woudstra <ericwo...@gmail.com> wrote: > - if (ret != NF_ACCEPT) > - return ret; > + if (ret == NF_ACCEPT) > + ret = nf_conntrack_in(skb, &bridge_state); > > - return nf_conntrack_in(skb, &bridge_state); > +do_not_track: > + if (offset) { > + __skb_push(skb, offset);
nf_conntrack_in() can free the skb, or steal it. But aside from this, I'm not sure this is a good idea to begin with, it feels like we start to reimplement br_netfilter.c . Perhaps it would be better to not push/pull but instead rename unsigned int nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state) to unsigned int nf_conntrack_inner(struct sk_buff *skb, const struct nf_hook_state *state, unsigned int nhoff) and add unsigned int nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state) { return nf_conntrack_inner(skb, state, skb_network_offset(skb)); } Or, alternatively, add struct nf_ct_pktoffs { u16 nhoff; u16 thoff; }; then populate that from nf_ct_bridge_pre(), then pass that to nf_conntrack_inner() (all names are suggestions, if you find something better thats fine). Its going to be more complicated than this, but my point is that e.g. nf_ct_get_tuple() already gets the l4 offset, so why not pass l3 offset too?