Hi Alin, On Thu, Nov 29, 2018 at 10:28:51AM +0100, Alin Nastac wrote: > Allow media streams that are not passing through this router. > > When enabled, the sip_external_media logic will leave SDP > payload untouched when it detects that interface towards INVITEd > party is the same with the one towards media endpoint. Sorry for catching up this now. Would you make for me a more detailed scenario? I love to keep such in the patch description, they are good for the record, specifically for this "tricky" helper. Thanks! > Signed-off-by: Alin Nastac <alin.nastac@xxxxxxxxx> > --- > net/netfilter/nf_conntrack_sip.c | 38 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 38 insertions(+) > > diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c > index c8d2b66..5416c08 100644 > --- a/net/netfilter/nf_conntrack_sip.c > +++ b/net/netfilter/nf_conntrack_sip.c > @@ -21,6 +21,8 @@ > #include <linux/tcp.h> > #include <linux/netfilter.h> > > +#include <net/route.h> > +#include <net/ip6_route.h> > #include <net/netfilter/nf_conntrack.h> > #include <net/netfilter/nf_conntrack_core.h> > #include <net/netfilter/nf_conntrack_expect.h> > @@ -54,6 +56,11 @@ module_param(sip_direct_media, int, 0600); > MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " > "endpoints only (default 1)"); > > +static int sip_external_media __read_mostly = 0; > +module_param(sip_external_media, int, 0600); > +MODULE_PARM_DESC(sip_external_media, "Expect Media streams between external " > + "endpoints (default 0)"); > + > const struct nf_nat_sip_hooks *nf_nat_sip_hooks; > EXPORT_SYMBOL_GPL(nf_nat_sip_hooks); > > @@ -861,6 +868,37 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, > if (!nf_inet_addr_cmp(daddr, &ct->tuplehash[dir].tuple.src.u3)) > return NF_ACCEPT; > saddr = &ct->tuplehash[!dir].tuple.src.u3; > + } else if (sip_external_media) { > + struct net_device *dev = skb_dst(skb)->dev; > + struct net *net = dev_net(dev); > + struct rtable *rt; > + struct flowi4 fl4 = {}; > + struct flowi6 fl6 = {}; > + struct dst_entry *dst = NULL; > + > + switch (nf_ct_l3num(ct)) { > + case NFPROTO_IPV4: > + fl4.daddr = daddr->ip; > + rt = ip_route_output_key(net, &fl4); > + if (!IS_ERR(rt)) > + dst = &rt->dst; > + break; > + > + case NFPROTO_IPV6: > + fl6.daddr = daddr->in6; > + dst = ip6_route_output(net, NULL, &fl6); > + if (dst->error) { > + dst_release(dst); > + dst = NULL; > + } > + break; > + } > + > + /* Don't predict any conntracks when media endpoint is reachable > + * through the same interface as the signalling peer. > + */ > + if (dst && dst->dev == dev) > + return NF_ACCEPT; > } > > /* We need to check whether the registration exists before attempting > -- > 2.7.4 >