nf_conntrack_rtsp: update to latest version
Update nf_conntrack_rtsp to latest version based on http://mike.it-loops.com/rtsp/ (rtsp-module-3.7-v2.tar.gz). Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> SVN-Revision: 43311
This commit is contained in:
parent
d460500a72
commit
2d09efcd26
3 changed files with 616 additions and 601 deletions
|
@ -235,10 +235,23 @@
|
|||
+#endif /* _NETFILTER_MIME_H */
|
||||
--- /dev/null
|
||||
+++ b/extensions/rtsp/nf_conntrack_rtsp.c
|
||||
@@ -0,0 +1,519 @@
|
||||
@@ -0,0 +1,576 @@
|
||||
+/*
|
||||
+ * RTSP extension for IP connection tracking
|
||||
+ * (C) 2003 by Tom Marshall <tmarshall at real.com>
|
||||
+ *
|
||||
+ * 2005-02-13: Harald Welte <laforge at netfilter.org>
|
||||
+ * - port to 2.6
|
||||
+ * - update to recent post-2.6.11 api changes
|
||||
+ * 2006-09-14: Steven Van Acker <deepstar at singularity.be>
|
||||
+ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack
|
||||
+ * 2007-04-18: Michael Guntsche <mike at it-loops.com>
|
||||
+ * - Port to new NF API
|
||||
+ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd
|
||||
+ * - fixed rtcp nat mapping and other port mapping fixes
|
||||
+ * - simple TEARDOWN request handling
|
||||
+ * - codestyle fixes and other less significant bug fixes
|
||||
+ *
|
||||
+ * based on ip_conntrack_irc.c
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
|
@ -257,13 +270,6 @@
|
|||
+ * With setup_timeout you can specify how long the system waits for
|
||||
+ * an expected data channel (default 300 seconds).
|
||||
+ *
|
||||
+ * 2005-02-13: Harald Welte <laforge at netfilter.org>
|
||||
+ * - port to 2.6
|
||||
+ * - update to recent post-2.6.11 api changes
|
||||
+ * 2006-09-14: Steven Van Acker <deepstar at singularity.be>
|
||||
+ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack
|
||||
+ * 2007-04-18: Michael Guntsche <mike at it-loops.com>
|
||||
+ * - Port to new NF API
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
|
@ -286,7 +292,6 @@
|
|||
+#include "netfilter_mime.h"
|
||||
+
|
||||
+#include <linux/ctype.h>
|
||||
+#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
|
||||
+
|
||||
+#define MAX_PORTS 8
|
||||
+static int ports[MAX_PORTS];
|
||||
|
@ -311,9 +316,13 @@
|
|||
+
|
||||
+unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ unsigned int matchoff, unsigned int matchlen,struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct nf_conntrack_expect *exp);
|
||||
+void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ unsigned int protoff,
|
||||
+#endif
|
||||
+ unsigned int matchoff, unsigned int matchlen,
|
||||
+ struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct nf_conntrack_expect *rtp_exp,
|
||||
+ struct nf_conntrack_expect *rtcp_exp);
|
||||
+
|
||||
+EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook);
|
||||
+
|
||||
|
@ -491,14 +500,6 @@
|
|||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+void expected(struct nf_conn *ct, struct nf_conntrack_expect *exp)
|
||||
+{
|
||||
+ typeof(nf_nat_rtsp_hook_expectfn) nf_nat_rtsp_expectfn;
|
||||
+ nf_nat_rtsp_expectfn = rcu_dereference(nf_nat_rtsp_hook_expectfn);
|
||||
+ if(nf_nat_rtsp_expectfn && ct->master->status & IPS_NAT_MASK) {
|
||||
+ nf_nat_rtsp_expectfn(ct,exp);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*** conntrack functions ***/
|
||||
+
|
||||
|
@ -506,7 +507,12 @@
|
|||
+
|
||||
+static inline int
|
||||
+help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen,
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
||||
+ unsigned int protoff)
|
||||
+#else
|
||||
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
|
||||
+#endif
|
||||
+{
|
||||
+ struct ip_ct_rtsp_expect expinfo;
|
||||
+
|
||||
|
@ -518,9 +524,11 @@
|
|||
+ uint dataoff = 0;
|
||||
+ int ret = NF_ACCEPT;
|
||||
+
|
||||
+ struct nf_conntrack_expect *exp;
|
||||
+ struct nf_conntrack_expect *rtp_exp;
|
||||
+ struct nf_conntrack_expect *rtcp_exp = NULL;
|
||||
+
|
||||
+ __be16 be_loport;
|
||||
+ __be16 be_hiport;
|
||||
+
|
||||
+ typeof(nf_nat_rtsp_hook) nf_nat_rtsp;
|
||||
+
|
||||
|
@ -542,14 +550,20 @@
|
|||
+ &transoff, &translen))
|
||||
+ break; /* not a valid message */
|
||||
+
|
||||
+ if (strncmp(pdata+cmdoff, "TEARDOWN ", 9) == 0) {
|
||||
+ pr_debug("teardown handled\n");
|
||||
+ nf_ct_remove_expectations(ct); /* FIXME must be session id aware */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
|
||||
+ continue; /* not a SETUP message */
|
||||
+
|
||||
+ pr_debug("found a setup message\n");
|
||||
+
|
||||
+ off = 0;
|
||||
+ if(translen) {
|
||||
+ if(translen)
|
||||
+ rtsp_parse_transport(pdata+transoff, translen, &expinfo);
|
||||
+ }
|
||||
+
|
||||
+ if (expinfo.loport == 0) {
|
||||
+ pr_debug("no udp transports found\n");
|
||||
|
@ -559,43 +573,83 @@
|
|||
+ pr_debug("udp transport found, ports=(%d,%hu,%hu)\n",
|
||||
+ (int)expinfo.pbtype, expinfo.loport, expinfo.hiport);
|
||||
+
|
||||
+ exp = nf_ct_expect_alloc(ct);
|
||||
+ if (!exp) {
|
||||
+
|
||||
+ be_loport = htons(expinfo.loport);
|
||||
+
|
||||
+ rtp_exp = nf_ct_expect_alloc(ct);
|
||||
+ if (rtp_exp == NULL) {
|
||||
+ ret = NF_DROP;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ be_loport = htons(expinfo.loport);
|
||||
+
|
||||
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
|
||||
+ &ct->tuplehash[!dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3,
|
||||
+ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT,
|
||||
+ nf_ct_l3num(ct),
|
||||
+ NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */
|
||||
+ &ct->tuplehash[!dir].tuple.dst.u3,
|
||||
+ IPPROTO_UDP, NULL, &be_loport);
|
||||
+
|
||||
+ exp->master = ct;
|
||||
+
|
||||
+ exp->expectfn = expected;
|
||||
+ exp->flags = 0;
|
||||
+ rtp_exp->flags = 0;
|
||||
+
|
||||
+ if (expinfo.pbtype == pb_range) {
|
||||
+ pr_debug("Changing expectation mask to handle multiple ports\n");
|
||||
+ //exp->mask.dst.u.udp.port = 0xfffe;
|
||||
+ pr_debug("setup expectation for rtcp\n");
|
||||
+
|
||||
+ be_hiport = htons(expinfo.hiport);
|
||||
+ rtcp_exp = nf_ct_expect_alloc(ct);
|
||||
+ if (rtcp_exp == NULL) {
|
||||
+ ret = NF_DROP;
|
||||
+ goto out1;
|
||||
+ }
|
||||
+
|
||||
+ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT,
|
||||
+ nf_ct_l3num(ct),
|
||||
+ NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */
|
||||
+ &ct->tuplehash[!dir].tuple.dst.u3,
|
||||
+ IPPROTO_UDP, NULL, &be_hiport);
|
||||
+
|
||||
+ rtcp_exp->flags = 0;
|
||||
+
|
||||
+ pr_debug("expect_related %pI4:%u-%u-%pI4:%u-%u\n",
|
||||
+ &rtp_exp->tuple.src.u3.ip,
|
||||
+ ntohs(rtp_exp->tuple.src.u.udp.port),
|
||||
+ ntohs(rtcp_exp->tuple.src.u.udp.port),
|
||||
+ &rtp_exp->tuple.dst.u3.ip,
|
||||
+ ntohs(rtp_exp->tuple.dst.u.udp.port),
|
||||
+ ntohs(rtcp_exp->tuple.dst.u.udp.port));
|
||||
+ } else {
|
||||
+ pr_debug("expect_related %pI4:%u-%pI4:%u\n",
|
||||
+ &exp->tuple.src.u3.ip,
|
||||
+ ntohs(exp->tuple.src.u.udp.port),
|
||||
+ &exp->tuple.dst.u3.ip,
|
||||
+ ntohs(exp->tuple.dst.u.udp.port));
|
||||
+ &rtp_exp->tuple.src.u3.ip,
|
||||
+ ntohs(rtp_exp->tuple.src.u.udp.port),
|
||||
+ &rtp_exp->tuple.dst.u3.ip,
|
||||
+ ntohs(rtp_exp->tuple.dst.u.udp.port));
|
||||
+ }
|
||||
+
|
||||
+ nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook);
|
||||
+ if (nf_nat_rtsp && ct->status & IPS_NAT_MASK)
|
||||
+ /* pass the request off to the nat helper */
|
||||
+ ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, &expinfo, exp);
|
||||
+ else if (nf_ct_expect_related(exp) != 0) {
|
||||
+ pr_info("nf_conntrack_expect_related failed\n");
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen,
|
||||
+ &expinfo, rtp_exp, rtcp_exp);
|
||||
+#else
|
||||
+ ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen,
|
||||
+ &expinfo, rtp_exp, rtcp_exp);
|
||||
+#endif
|
||||
+ else {
|
||||
+ if (nf_ct_expect_related(rtp_exp) == 0) {
|
||||
+ if (rtcp_exp && nf_ct_expect_related(rtcp_exp) != 0) {
|
||||
+ nf_ct_unexpect_related(rtp_exp);
|
||||
+ pr_info("nf_conntrack_expect_related failed for rtcp\n");
|
||||
+ ret = NF_DROP;
|
||||
+ }
|
||||
+ nf_ct_expect_put(exp);
|
||||
+ } else {
|
||||
+ pr_info("nf_conntrack_expect_related failed for rtp\n");
|
||||
+ ret = NF_DROP;
|
||||
+ }
|
||||
+ }
|
||||
+ if (rtcp_exp) {
|
||||
+ nf_ct_expect_put(rtcp_exp);
|
||||
+ }
|
||||
+out1:
|
||||
+ nf_ct_expect_put(rtp_exp);
|
||||
+ goto out;
|
||||
+ }
|
||||
+out:
|
||||
|
@ -627,7 +681,7 @@
|
|||
+ }
|
||||
+
|
||||
+ /* Not whole TCP header? */
|
||||
+ th = skb_header_pointer(skb,protoff, sizeof(_tcph), &_tcph);
|
||||
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
|
||||
+
|
||||
+ if (!th)
|
||||
+ return NF_ACCEPT;
|
||||
|
@ -657,7 +711,11 @@
|
|||
+
|
||||
+ switch (CTINFO2DIR(ctinfo)) {
|
||||
+ case IP_CT_DIR_ORIGINAL:
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff);
|
||||
+#else
|
||||
+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo);
|
||||
+#endif
|
||||
+ break;
|
||||
+ case IP_CT_DIR_REPLY:
|
||||
+ pr_debug("IP_CT_DIR_REPLY\n");
|
||||
|
@ -714,6 +772,7 @@
|
|||
+ /* If no port given, default to standard rtsp port */
|
||||
+ if (ports[0] == 0) {
|
||||
+ ports[0] = RTSP_PORT;
|
||||
+ num_ports = 1;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
|
||||
|
@ -722,8 +781,6 @@
|
|||
+ hlpr->tuple.src.l3num = AF_INET;
|
||||
+ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
|
||||
+ hlpr->tuple.dst.protonum = IPPROTO_TCP;
|
||||
+ //hlpr->mask.src.u.tcp.port = 0xFFFF;
|
||||
+ //hlpr->mask.dst.protonum = 0xFF;
|
||||
+ hlpr->expect_policy = &rtsp_exp_policy;
|
||||
+ hlpr->me = THIS_MODULE;
|
||||
+ hlpr->help = help;
|
||||
|
@ -734,8 +791,12 @@
|
|||
+ } else {
|
||||
+ sprintf(tmpname, "rtsp-%d", i);
|
||||
+ }
|
||||
+ hlpr->name = tmpname;
|
||||
+
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
|
||||
+ strlcpy(hlpr->name, tmpname, sizeof(hlpr->name));
|
||||
+#else
|
||||
+ hlpr->name = tmpname;
|
||||
+#endif
|
||||
+ pr_debug("port #%d: %d\n", i, ports[i]);
|
||||
+
|
||||
+ ret = nf_conntrack_helper_register(hlpr);
|
||||
|
@ -745,19 +806,15 @@
|
|||
+ fini();
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+ num_ports++;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
+
|
||||
+EXPORT_SYMBOL(nf_nat_rtsp_hook_expectfn);
|
||||
+
|
||||
--- /dev/null
|
||||
+++ b/extensions/rtsp/nf_conntrack_rtsp.h
|
||||
@@ -0,0 +1,63 @@
|
||||
@@ -0,0 +1,72 @@
|
||||
+/*
|
||||
+ * RTSP extension for IP connection tracking.
|
||||
+ * (C) 2003 by Tom Marshall <tmarshall at real.com>
|
||||
|
@ -767,12 +824,18 @@
|
|||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * as published by the Free Software Foundation; either version
|
||||
+ * 2 of the License, or (at your option) any later version.
|
||||
+ */
|
||||
+ *
|
||||
+ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd
|
||||
+ * - conditional compilation for kernel 3.7
|
||||
+ * - port mapping improvements
|
||||
+*/
|
||||
+#ifndef _IP_CONNTRACK_RTSP_H
|
||||
+#define _IP_CONNTRACK_RTSP_H
|
||||
+
|
||||
+#include <linux/version.h>
|
||||
+
|
||||
+//#define IP_NF_RTSP_DEBUG 1
|
||||
+#define IP_NF_RTSP_VERSION "0.6.21"
|
||||
+#define IP_NF_RTSP_VERSION "0.7"
|
||||
+
|
||||
+#ifdef __KERNEL__
|
||||
+/* port block types */
|
||||
|
@ -810,11 +873,14 @@
|
|||
+
|
||||
+extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ unsigned int matchoff, unsigned int matchlen,
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ unsigned int protoff,
|
||||
+#endif
|
||||
+ unsigned int matchoff,
|
||||
+ unsigned int matchlen,
|
||||
+ struct ip_ct_rtsp_expect *prtspexp,
|
||||
+ struct nf_conntrack_expect *exp);
|
||||
+
|
||||
+extern void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
|
||||
+ struct nf_conntrack_expect *rtp_exp,
|
||||
+ struct nf_conntrack_expect *rtcp_exp);
|
||||
+
|
||||
+#define RTSP_PORT 554
|
||||
+
|
||||
|
@ -823,10 +889,16 @@
|
|||
+#endif /* _IP_CONNTRACK_RTSP_H */
|
||||
--- /dev/null
|
||||
+++ b/extensions/rtsp/nf_nat_rtsp.c
|
||||
@@ -0,0 +1,491 @@
|
||||
@@ -0,0 +1,617 @@
|
||||
+/*
|
||||
+ * RTSP extension for TCP NAT alteration
|
||||
+ * (C) 2003 by Tom Marshall <tmarshall at real.com>
|
||||
+ *
|
||||
+ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd
|
||||
+ * - fixed rtcp nat mapping and other port mapping fixes
|
||||
+ * - fixed system hard lock because of bug in the parser
|
||||
+ * - codestyle fixes and less significant fixes
|
||||
+ *
|
||||
+ * based on ip_nat_irc.c
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
|
@ -857,9 +929,14 @@
|
|||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/version.h>
|
||||
+#include <net/tcp.h>
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+# include <net/netfilter/nf_nat.h>
|
||||
+#else
|
||||
+# include <net/netfilter/nf_nat_rule.h>
|
||||
+#endif
|
||||
+#include <net/netfilter/nf_nat_helper.h>
|
||||
+#include <net/netfilter/nf_nat_rule.h>
|
||||
+#include "nf_conntrack_rtsp.h"
|
||||
+#include <net/netfilter/nf_conntrack_expect.h>
|
||||
+
|
||||
|
@ -871,8 +948,6 @@
|
|||
+#define NF_NEED_MIME_NEXTLINE
|
||||
+#include "netfilter_mime.h"
|
||||
+
|
||||
+#include "../compat_xtables.h"
|
||||
+
|
||||
+#define MAX_PORTS 8
|
||||
+#define DSTACT_AUTO 0
|
||||
+#define DSTACT_STRIP 1
|
||||
|
@ -884,6 +959,8 @@
|
|||
+static u_int32_t extip = 0;
|
||||
+static int dstact = 0;
|
||||
+
|
||||
+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp);
|
||||
+
|
||||
+MODULE_AUTHOR("Tom Marshall <tmarshall at real.com>");
|
||||
+MODULE_DESCRIPTION("RTSP network address translation module");
|
||||
+MODULE_LICENSE("GPL");
|
||||
|
@ -906,6 +983,22 @@
|
|||
+ *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata;
|
||||
+}
|
||||
+
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+/* copy of sip_sprintf_addr */
|
||||
+static int rtsp_sprintf_addr(const struct nf_conn *ct, char *buffer,
|
||||
+ const union nf_inet_addr *addr, bool delim)
|
||||
+{
|
||||
+ if (nf_ct_l3num(ct) == NFPROTO_IPV4) {
|
||||
+ return sprintf(buffer, "%pI4", &addr->ip);
|
||||
+ } else {
|
||||
+ if (delim)
|
||||
+ return sprintf(buffer, "[%pI6c]", &addr->ip6);
|
||||
+ else
|
||||
+ return sprintf(buffer, "%pI6c", &addr->ip6);
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/*** nat functions ***/
|
||||
+
|
||||
+/*
|
||||
|
@ -927,7 +1020,11 @@
|
|||
+ */
|
||||
+static int
|
||||
+rtsp_mangle_tran(enum ip_conntrack_info ctinfo,
|
||||
+ struct nf_conntrack_expect* exp,
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ unsigned int protoff,
|
||||
+#endif
|
||||
+ struct nf_conntrack_expect* rtp_exp,
|
||||
+ struct nf_conntrack_expect* rtcp_exp,
|
||||
+ struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct sk_buff* skb, uint tranoff, uint tranlen)
|
||||
+{
|
||||
|
@ -938,15 +1035,24 @@
|
|||
+ uint rbuf1len; /* Replacement len (one port) */
|
||||
+ char rbufa[16]; /* Replacement buffer (all ports) */
|
||||
+ uint rbufalen; /* Replacement len (all ports) */
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ union nf_inet_addr newip;
|
||||
+#else
|
||||
+ u_int32_t newip;
|
||||
+#endif
|
||||
+ u_int16_t loport, hiport;
|
||||
+ uint off = 0;
|
||||
+ uint diff; /* Number of bytes we removed */
|
||||
+
|
||||
+ struct nf_conn *ct = exp->master;
|
||||
+ struct nf_conntrack_tuple *t;
|
||||
+ struct nf_conn *ct = rtp_exp->master;
|
||||
+ /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */
|
||||
+ struct nf_conntrack_tuple *rtp_t;
|
||||
+
|
||||
+ char szextaddr[15+1];
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ char szextaddr[INET6_ADDRSTRLEN];
|
||||
+#else
|
||||
+ char szextaddr[INET_ADDRSTRLEN];
|
||||
+#endif
|
||||
+ uint extaddrlen;
|
||||
+ int is_stun;
|
||||
+
|
||||
|
@ -955,107 +1061,114 @@
|
|||
+
|
||||
+ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
|
||||
+ tranlen < 10 || !iseol(ptran[tranlen-1]) ||
|
||||
+ nf_strncasecmp(ptran, "Transport:", 10) != 0)
|
||||
+ {
|
||||
+ nf_strncasecmp(ptran, "Transport:", 10) != 0) {
|
||||
+ pr_info("sanity check failed\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ off += 10;
|
||||
+ SKIP_WSPACE(ptcp+tranoff, tranlen, off);
|
||||
+
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3;
|
||||
+ rtp_t = &rtp_exp->tuple;
|
||||
+ rtp_t->dst.u3 = newip;
|
||||
+ if (rtcp_exp) {
|
||||
+ rtcp_exp->tuple.dst.u3 = newip;
|
||||
+ }
|
||||
+ extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip
|
||||
+ pr_debug("stunaddr=%s (auto)\n", szextaddr);
|
||||
+#else
|
||||
+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
|
||||
+ t = &exp->tuple;
|
||||
+ t->dst.u3.ip = newip;
|
||||
+
|
||||
+ rtp_t = &rtp_exp->tuple;
|
||||
+ rtp_t->dst.u3.ip = newip;
|
||||
+ if (rtcp_exp) {
|
||||
+ rtcp_exp->tuple.dst.u3.ip = newip;
|
||||
+ }
|
||||
+ extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip)
|
||||
+ : sprintf(szextaddr, "%pI4", &newip);
|
||||
+ pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
|
||||
+
|
||||
+#endif
|
||||
+ hiport = 0;
|
||||
+ rbuf1len = rbufalen = 0;
|
||||
+ switch (prtspexp->pbtype)
|
||||
+ {
|
||||
+ switch (prtspexp->pbtype) {
|
||||
+ case pb_single:
|
||||
+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
|
||||
+ {
|
||||
+ t->dst.u.udp.port = htons(loport);
|
||||
+ if (nf_ct_expect_related(exp) == 0)
|
||||
+ {
|
||||
+ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */
|
||||
+ rtp_t->dst.u.udp.port = htons(loport);
|
||||
+ if (nf_ct_expect_related(rtp_exp) == 0) {
|
||||
+ pr_debug("using port %hu\n", loport);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (loport != 0)
|
||||
+ {
|
||||
+ if (loport != 0) {
|
||||
+ rbuf1len = sprintf(rbuf1, "%hu", loport);
|
||||
+ rbufalen = sprintf(rbufa, "%hu", loport);
|
||||
+ }
|
||||
+ break;
|
||||
+ case pb_range:
|
||||
+ for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
|
||||
+ {
|
||||
+ t->dst.u.udp.port = htons(loport);
|
||||
+ if (nf_ct_expect_related(exp) == 0)
|
||||
+ {
|
||||
+ hiport = loport + 1; //~exp->mask.dst.u.udp.port;
|
||||
+ pr_debug("using ports %hu-%hu\n", loport, hiport);
|
||||
+ for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */
|
||||
+ rtp_t->dst.u.udp.port = htons(loport);
|
||||
+ if (nf_ct_expect_related(rtp_exp) != 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ hiport = loport + 1;
|
||||
+ rtcp_exp->tuple.dst.u.udp.port = htons(hiport);
|
||||
+ if (nf_ct_expect_related(rtcp_exp) != 0) {
|
||||
+ nf_ct_unexpect_related(rtp_exp);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* FIXME: invalid print in case of ipv6 */
|
||||
+ pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n",
|
||||
+ &rtp_exp->tuple.src.u3.ip,
|
||||
+ ntohs(rtp_exp->tuple.src.u.udp.port),
|
||||
+ ntohs(rtcp_exp->tuple.src.u.udp.port),
|
||||
+ &rtp_exp->tuple.dst.u3.ip,
|
||||
+ ntohs(rtp_exp->tuple.dst.u.udp.port),
|
||||
+ ntohs(rtcp_exp->tuple.dst.u.udp.port));
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (loport != 0)
|
||||
+ {
|
||||
+ if (loport != 0) {
|
||||
+ rbuf1len = sprintf(rbuf1, "%hu", loport);
|
||||
+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
|
||||
+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
|
||||
+ }
|
||||
+ break;
|
||||
+ case pb_discon:
|
||||
+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
|
||||
+ {
|
||||
+ t->dst.u.udp.port = htons(loport);
|
||||
+ if (nf_ct_expect_related(exp) == 0)
|
||||
+ {
|
||||
+ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */
|
||||
+ rtp_t->dst.u.udp.port = htons(loport);
|
||||
+ if (nf_ct_expect_related(rtp_exp) == 0) {
|
||||
+ pr_debug("using port %hu (1 of 2)\n", loport);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
|
||||
+ {
|
||||
+ t->dst.u.udp.port = htons(hiport);
|
||||
+ if (nf_ct_expect_related(exp) == 0)
|
||||
+ {
|
||||
+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */
|
||||
+ rtp_t->dst.u.udp.port = htons(hiport);
|
||||
+ if (nf_ct_expect_related(rtp_exp) == 0) {
|
||||
+ pr_debug("using port %hu (2 of 2)\n", hiport);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (loport != 0 && hiport != 0)
|
||||
+ {
|
||||
+ if (loport != 0 && hiport != 0) {
|
||||
+ rbuf1len = sprintf(rbuf1, "%hu", loport);
|
||||
+ if (hiport == loport+1)
|
||||
+ {
|
||||
+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
|
||||
+ }
|
||||
+ rbufalen = sprintf(rbufa, hiport == loport+1 ?
|
||||
+ "%hu-%hu":"%hu/%hu", loport, hiport);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (rbuf1len == 0)
|
||||
+ {
|
||||
+ return 0; /* cannot get replacement port(s) */
|
||||
+ }
|
||||
+
|
||||
+ /* Transport: tran;field;field=val,tran;field;field=val,... */
|
||||
+ while (off < tranlen)
|
||||
+ {
|
||||
+ /* Transport: tran;field;field=val,tran;field;field=val,...
|
||||
+ `off` is set to the start of Transport value from start of line
|
||||
+ */
|
||||
+ while (off < tranlen) {
|
||||
+ uint saveoff;
|
||||
+ const char* pparamend;
|
||||
+ uint nextparamoff;
|
||||
+
|
||||
+ pparamend = memchr(ptran+off, ',', tranlen-off);
|
||||
+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
|
||||
+ nextparamoff = pparamend-ptcp;
|
||||
+ nextparamoff = pparamend-ptran;
|
||||
+
|
||||
+ /*
|
||||
+ * We pass over each param twice. On the first pass, we look for a
|
||||
|
@ -1065,28 +1178,43 @@
|
|||
+ */
|
||||
+ is_stun = 0;
|
||||
+ saveoff = off;
|
||||
+ while (off < nextparamoff)
|
||||
+ {
|
||||
+ while (off < nextparamoff) {
|
||||
+ const char* pfieldend;
|
||||
+ uint nextfieldoff;
|
||||
+
|
||||
+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
|
||||
+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
|
||||
+
|
||||
+ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
|
||||
+ {
|
||||
+ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) {
|
||||
+ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
|
||||
+ {
|
||||
+ is_stun = 1;
|
||||
+
|
||||
+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) {
|
||||
+ uint dstoff = (ptran-ptcp)+off;
|
||||
+ uint dstlen = nextfieldoff-off;
|
||||
+ char* pdstrep = NULL;
|
||||
+ uint dstreplen = 0;
|
||||
+ diff = dstlen;
|
||||
+ if (dstact == DSTACT_AUTO && !is_stun) {
|
||||
+ pr_debug("RTSP: replace dst addr\n");
|
||||
+ dstoff += 12;
|
||||
+ dstlen -= 13;
|
||||
+ pdstrep = szextaddr;
|
||||
+ dstreplen = extaddrlen;
|
||||
+ diff = nextfieldoff-off-13-extaddrlen;
|
||||
+ }
|
||||
+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
|
||||
+ {
|
||||
+ diff = nextfieldoff-off;
|
||||
+
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
|
||||
+ dstoff, dstlen, pdstrep, dstreplen)) {
|
||||
+#else
|
||||
+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
+ off, diff, NULL, 0))
|
||||
+ {
|
||||
+ dstoff, dstlen, pdstrep, dstreplen)) {
|
||||
+#endif
|
||||
+ /* mangle failed, all we can do is bail */
|
||||
+ nf_ct_unexpect_related(exp);
|
||||
+ nf_ct_unexpect_related(rtp_exp);
|
||||
+ if (rtcp_exp)
|
||||
+ nf_ct_unexpect_related(rtcp_exp);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ get_skb_tcpdata(skb, &ptcp, &tcplen);
|
||||
|
@ -1099,21 +1227,19 @@
|
|||
+
|
||||
+ off = nextfieldoff;
|
||||
+ }
|
||||
+
|
||||
+ if (is_stun)
|
||||
+ {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ off = saveoff;
|
||||
+ while (off < nextparamoff)
|
||||
+ {
|
||||
+ while (off < nextparamoff) {
|
||||
+ const char* pfieldend;
|
||||
+ uint nextfieldoff;
|
||||
+
|
||||
+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
|
||||
+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
|
||||
+
|
||||
+ if (strncmp(ptran+off, "client_port=", 12) == 0)
|
||||
+ {
|
||||
+ if (strncmp(ptran+off, "client_port=", 12) == 0) {
|
||||
+ u_int16_t port;
|
||||
+ uint numlen;
|
||||
+ uint origoff;
|
||||
|
@ -1127,14 +1253,10 @@
|
|||
+ numlen = nf_strtou16(ptran+off, &port);
|
||||
+ off += numlen;
|
||||
+ origlen += numlen;
|
||||
+ if (port != prtspexp->loport)
|
||||
+ {
|
||||
+ if (port != prtspexp->loport) {
|
||||
+ pr_debug("multiple ports found, port %hu ignored\n", port);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (ptran[off] == '-' || ptran[off] == '/')
|
||||
+ {
|
||||
+ } else {
|
||||
+ if (ptran[off] == '-' || ptran[off] == '/') {
|
||||
+ off++;
|
||||
+ origlen++;
|
||||
+ numlen = nf_strtou16(ptran+off, &port);
|
||||
|
@ -1152,11 +1274,17 @@
|
|||
+ * parameter 4 below is offset from start of tcp data.
|
||||
+ */
|
||||
+ diff = origlen-rbuflen;
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
|
||||
+ origoff, origlen, rbuf, rbuflen)) {
|
||||
+#else
|
||||
+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
+ origoff, origlen, rbuf, rbuflen))
|
||||
+ {
|
||||
+ origoff, origlen, rbuf, rbuflen)) {
|
||||
+#endif
|
||||
+ /* mangle failed, all we can do is bail */
|
||||
+ nf_ct_unexpect_related(exp);
|
||||
+ nf_ct_unexpect_related(rtp_exp);
|
||||
+ if (rtcp_exp)
|
||||
+ nf_ct_unexpect_related(rtcp_exp);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ get_skb_tcpdata(skb, &ptcp, &tcplen);
|
||||
|
@ -1178,8 +1306,13 @@
|
|||
+
|
||||
+static uint
|
||||
+help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
|
||||
+ unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct nf_conntrack_expect* exp)
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ unsigned int protoff,
|
||||
+#endif
|
||||
+ unsigned int matchoff, unsigned int matchlen,
|
||||
+ struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct nf_conntrack_expect* rtp_exp,
|
||||
+ struct nf_conntrack_expect* rtcp_exp)
|
||||
+{
|
||||
+ char* ptcp;
|
||||
+ uint tcplen;
|
||||
|
@ -1188,6 +1321,12 @@
|
|||
+ uint lineoff;
|
||||
+ uint linelen;
|
||||
+ uint off;
|
||||
+ int dir = CTINFO2DIR(ctinfo);
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3;
|
||||
+#else
|
||||
+ __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip;
|
||||
+#endif
|
||||
+
|
||||
+ //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
|
||||
+ //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
|
||||
|
@ -1198,28 +1337,47 @@
|
|||
+ off = hdrsoff;
|
||||
+ pr_debug("NAT rtsp help_out\n");
|
||||
+
|
||||
+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
|
||||
+ {
|
||||
+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) {
|
||||
+ if (linelen == 0)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (off > hdrsoff+hdrslen)
|
||||
+ {
|
||||
+
|
||||
+ if (off > hdrsoff+hdrslen) {
|
||||
+ pr_info("!! overrun !!");
|
||||
+ break;
|
||||
+ }
|
||||
+ pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
|
||||
+
|
||||
+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
|
||||
+ {
|
||||
+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) {
|
||||
+ uint oldtcplen = tcplen;
|
||||
+ pr_debug("hdr: Transport\n");
|
||||
+ if (!rtsp_mangle_tran(ctinfo, exp, prtspexp, skb, lineoff, linelen))
|
||||
+ {
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp,
|
||||
+ prtspexp, skb, lineoff, linelen)) {
|
||||
+#else
|
||||
+ if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp,
|
||||
+ skb, lineoff, linelen)) {
|
||||
+#endif
|
||||
+ pr_debug("hdr: Transport mangle failed");
|
||||
+ break;
|
||||
+ }
|
||||
+ rtp_exp->expectfn = nf_nat_rtsp_expected;
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ rtp_exp->saved_addr = saddr;
|
||||
+#else
|
||||
+ rtp_exp->saved_ip = saddr;
|
||||
+#endif
|
||||
+ rtp_exp->saved_proto.udp.port = htons(prtspexp->loport);
|
||||
+ rtp_exp->dir = !dir;
|
||||
+ if (rtcp_exp) {
|
||||
+ rtcp_exp->expectfn = nf_nat_rtsp_expected;
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ rtcp_exp->saved_addr = saddr;
|
||||
+#else
|
||||
+ rtcp_exp->saved_ip = saddr;
|
||||
+#endif
|
||||
+ rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport);
|
||||
+ rtcp_exp->dir = !dir;
|
||||
+ }
|
||||
+ get_skb_tcpdata(skb, &ptcp, &tcplen);
|
||||
+ hdrslen -= (oldtcplen-tcplen);
|
||||
+ off -= (oldtcplen-tcplen);
|
||||
|
@ -1233,17 +1391,27 @@
|
|||
+}
|
||||
+
|
||||
+static unsigned int
|
||||
+help(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
|
||||
+ unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct nf_conntrack_expect* exp)
|
||||
+nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ unsigned int protoff,
|
||||
+#endif
|
||||
+ unsigned int matchoff, unsigned int matchlen,
|
||||
+ struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct nf_conntrack_expect* rtp_exp,
|
||||
+ struct nf_conntrack_expect* rtcp_exp)
|
||||
+{
|
||||
+ int dir = CTINFO2DIR(ctinfo);
|
||||
+ int rc = NF_ACCEPT;
|
||||
+
|
||||
+ switch (dir)
|
||||
+ {
|
||||
+ switch (dir) {
|
||||
+ case IP_CT_DIR_ORIGINAL:
|
||||
+ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, exp);
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp,
|
||||
+ rtp_exp, rtcp_exp);
|
||||
+#else
|
||||
+ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp,
|
||||
+ rtp_exp, rtcp_exp);
|
||||
+#endif
|
||||
+ break;
|
||||
+ case IP_CT_DIR_REPLY:
|
||||
+ pr_debug("unmangle ! %u\n", ctinfo);
|
||||
|
@ -1256,35 +1424,60 @@
|
|||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static void expected(struct nf_conn* ct, struct nf_conntrack_expect *exp)
|
||||
+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp)
|
||||
+{
|
||||
+ struct nf_nat_ipv4_multi_range_compat mr;
|
||||
+ u_int32_t newdstip, newsrcip, newip;
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ struct nf_nat_range range;
|
||||
+#else
|
||||
+ struct nf_nat_ipv4_range range;
|
||||
+#endif
|
||||
+
|
||||
+ struct nf_conn *master = ct->master;
|
||||
+ /* This must be a fresh one. */
|
||||
+ BUG_ON(ct->status & IPS_NAT_DONE_MASK);
|
||||
+
|
||||
+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
||||
+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
||||
+ //FIXME (how to port that ?)
|
||||
+ //code from 2.4 : newip = (HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC) ? newsrcip : newdstip;
|
||||
+ newip = newdstip;
|
||||
+ /* For DST manip, map port here to where it's expected. */
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ range.min_proto = range.max_proto = exp->saved_proto;
|
||||
+ range.min_addr = range.max_addr = exp->saved_addr;
|
||||
+#else
|
||||
+ range.min = range.max = exp->saved_proto;
|
||||
+ range.min_ip = range.max_ip = exp->saved_ip;
|
||||
+#endif
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
|
||||
+ range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
|
||||
+ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
|
||||
+#else
|
||||
+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
|
||||
+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
|
||||
+#endif
|
||||
+
|
||||
+ pr_debug("newsrcip=%pI4, newdstip=%pI4, newip=%pI4\n",
|
||||
+ &newsrcip, &newdstip, &newip);
|
||||
+
|
||||
+ mr.rangesize = 1;
|
||||
+ // We don't want to manip the per-protocol, just the IPs.
|
||||
+ mr.range[0].flags = NF_NAT_RANGE_MAP_IPS;
|
||||
+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
|
||||
+
|
||||
+ nf_nat_setup_info(ct, &mr.range[0], NF_NAT_MANIP_DST);
|
||||
+ /* Change src to where master sends to, but only if the connection
|
||||
+ * actually came from the same source. */
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
|
||||
+ if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
|
||||
+ &ct->master->tuplehash[exp->dir].tuple.src.u3)) {
|
||||
+ range.min_addr = range.max_addr
|
||||
+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3;
|
||||
+#else
|
||||
+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip ==
|
||||
+ ct->master->tuplehash[exp->dir].tuple.src.u3.ip) {
|
||||
+ range.min_ip = range.max_ip
|
||||
+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
|
||||
+#endif
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
|
||||
+ range.flags = NF_NAT_RANGE_MAP_IPS;
|
||||
+ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
|
||||
+#else
|
||||
+ range.flags = IP_NAT_RANGE_MAP_IPS;
|
||||
+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
|
||||
+#endif
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ nf_nat_rtsp_hook = NULL;
|
||||
+ nf_nat_rtsp_hook_expectfn = NULL;
|
||||
+ rcu_assign_pointer(nf_nat_rtsp_hook, NULL);
|
||||
+ synchronize_net();
|
||||
+}
|
||||
+
|
||||
|
@ -1293,8 +1486,7 @@
|
|||
+ printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
|
||||
+
|
||||
+ BUG_ON(nf_nat_rtsp_hook);
|
||||
+ nf_nat_rtsp_hook = help;
|
||||
+ nf_nat_rtsp_hook_expectfn = &expected;
|
||||
+ rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp);
|
||||
+
|
||||
+ if (stunaddr != NULL)
|
||||
+ extip = in_aton(stunaddr);
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
--- a/extensions/rtsp/nf_conntrack_rtsp.c
|
||||
+++ b/extensions/rtsp/nf_conntrack_rtsp.c
|
||||
@@ -28,6 +28,7 @@
|
||||
* - Port to new NF API
|
||||
*/
|
||||
|
||||
+#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/ip.h>
|
||||
@@ -496,7 +497,11 @@ init(void)
|
||||
} else {
|
||||
sprintf(tmpname, "rtsp-%d", i);
|
||||
}
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
|
||||
+ strncpy(hlpr->name, tmpname, sizeof(hlpr->name));
|
||||
+#else
|
||||
hlpr->name = tmpname;
|
||||
+#endif
|
||||
|
||||
pr_debug("port #%d: %d\n", i, ports[i]);
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
--- a/extensions/rtsp/nf_conntrack_rtsp.c
|
||||
+++ b/extensions/rtsp/nf_conntrack_rtsp.c
|
||||
@@ -73,7 +73,7 @@ static DEFINE_SPINLOCK(rtsp_buffer_lock)
|
||||
static struct nf_conntrack_expect_policy rtsp_exp_policy;
|
||||
|
||||
unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb,
|
||||
- enum ip_conntrack_info ctinfo,
|
||||
+ enum ip_conntrack_info ctinfo, unsigned int protoff,
|
||||
unsigned int matchoff, unsigned int matchlen,struct ip_ct_rtsp_expect* prtspexp,
|
||||
struct nf_conntrack_expect *exp);
|
||||
void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
|
||||
@@ -269,7 +269,7 @@ void expected(struct nf_conn *ct, struct
|
||||
|
||||
static inline int
|
||||
help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen,
|
||||
- struct nf_conn *ct, enum ip_conntrack_info ctinfo)
|
||||
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int protoff)
|
||||
{
|
||||
struct ip_ct_rtsp_expect expinfo;
|
||||
|
||||
@@ -353,7 +353,7 @@ help_out(struct sk_buff *skb, unsigned c
|
||||
nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook);
|
||||
if (nf_nat_rtsp && ct->status & IPS_NAT_MASK)
|
||||
/* pass the request off to the nat helper */
|
||||
- ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, &expinfo, exp);
|
||||
+ ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen, &expinfo, exp);
|
||||
else if (nf_ct_expect_related(exp) != 0) {
|
||||
pr_info("nf_conntrack_expect_related failed\n");
|
||||
ret = NF_DROP;
|
||||
@@ -420,7 +420,7 @@ static int help(struct sk_buff *skb, uns
|
||||
|
||||
switch (CTINFO2DIR(ctinfo)) {
|
||||
case IP_CT_DIR_ORIGINAL:
|
||||
- ret = help_out(skb, rb_ptr, datalen, ct, ctinfo);
|
||||
+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff);
|
||||
break;
|
||||
case IP_CT_DIR_REPLY:
|
||||
pr_debug("IP_CT_DIR_REPLY\n");
|
||||
--- a/extensions/rtsp/nf_conntrack_rtsp.h
|
||||
+++ b/extensions/rtsp/nf_conntrack_rtsp.h
|
||||
@@ -50,6 +50,7 @@ struct ip_ct_rtsp_expect
|
||||
|
||||
extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
+ unsigned int protoff,
|
||||
unsigned int matchoff, unsigned int matchlen,
|
||||
struct ip_ct_rtsp_expect *prtspexp,
|
||||
struct nf_conntrack_expect *exp);
|
||||
--- a/extensions/rtsp/nf_nat_rtsp.c
|
||||
+++ b/extensions/rtsp/nf_nat_rtsp.c
|
||||
@@ -32,10 +32,10 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <net/tcp.h>
|
||||
+#include <net/netfilter/nf_conntrack_expect.h>
|
||||
#include <net/netfilter/nf_nat_helper.h>
|
||||
-#include <net/netfilter/nf_nat_rule.h>
|
||||
+#include <net/netfilter/nf_nat.h>
|
||||
#include "nf_conntrack_rtsp.h"
|
||||
-#include <net/netfilter/nf_conntrack_expect.h>
|
||||
|
||||
#include <linux/inet.h>
|
||||
#include <linux/ctype.h>
|
||||
@@ -102,8 +102,8 @@ get_skb_tcpdata(struct sk_buff* skb, cha
|
||||
static int
|
||||
rtsp_mangle_tran(enum ip_conntrack_info ctinfo,
|
||||
struct nf_conntrack_expect* exp,
|
||||
- struct ip_ct_rtsp_expect* prtspexp,
|
||||
- struct sk_buff* skb, uint tranoff, uint tranlen)
|
||||
+ struct ip_ct_rtsp_expect* prtspexp,
|
||||
+ struct sk_buff* skb, uint protoff, uint tranoff, uint tranlen)
|
||||
{
|
||||
char* ptcp;
|
||||
uint tcplen;
|
||||
@@ -256,7 +256,7 @@ rtsp_mangle_tran(enum ip_conntrack_info
|
||||
if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
|
||||
{
|
||||
diff = nextfieldoff-off;
|
||||
- if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
|
||||
off, diff, NULL, 0))
|
||||
{
|
||||
/* mangle failed, all we can do is bail */
|
||||
@@ -326,7 +326,7 @@ rtsp_mangle_tran(enum ip_conntrack_info
|
||||
* parameter 4 below is offset from start of tcp data.
|
||||
*/
|
||||
diff = origlen-rbuflen;
|
||||
- if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
|
||||
origoff, origlen, rbuf, rbuflen))
|
||||
{
|
||||
/* mangle failed, all we can do is bail */
|
||||
@@ -351,7 +351,7 @@ rtsp_mangle_tran(enum ip_conntrack_info
|
||||
}
|
||||
|
||||
static uint
|
||||
-help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
|
||||
+help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, unsigned int protoff,
|
||||
unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp,
|
||||
struct nf_conntrack_expect* exp)
|
||||
{
|
||||
@@ -389,7 +389,7 @@ help_out(struct sk_buff *skb, enum ip_co
|
||||
{
|
||||
uint oldtcplen = tcplen;
|
||||
pr_debug("hdr: Transport\n");
|
||||
- if (!rtsp_mangle_tran(ctinfo, exp, prtspexp, skb, lineoff, linelen))
|
||||
+ if (!rtsp_mangle_tran(ctinfo, exp, prtspexp, skb, protoff, lineoff, linelen))
|
||||
{
|
||||
pr_debug("hdr: Transport mangle failed");
|
||||
break;
|
||||
@@ -407,7 +407,7 @@ help_out(struct sk_buff *skb, enum ip_co
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
-help(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
|
||||
+help(struct sk_buff *skb, enum ip_conntrack_info ctinfo, unsigned int protoff,
|
||||
unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp,
|
||||
struct nf_conntrack_expect* exp)
|
||||
{
|
||||
@@ -417,7 +417,7 @@ help(struct sk_buff *skb, enum ip_conntr
|
||||
switch (dir)
|
||||
{
|
||||
case IP_CT_DIR_ORIGINAL:
|
||||
- rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, exp);
|
||||
+ rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, exp);
|
||||
break;
|
||||
case IP_CT_DIR_REPLY:
|
||||
pr_debug("unmangle ! %u\n", ctinfo);
|
||||
@@ -432,7 +432,7 @@ help(struct sk_buff *skb, enum ip_conntr
|
||||
|
||||
static void expected(struct nf_conn* ct, struct nf_conntrack_expect *exp)
|
||||
{
|
||||
- struct nf_nat_ipv4_multi_range_compat mr;
|
||||
+ struct nf_nat_range nr;
|
||||
u_int32_t newdstip, newsrcip, newip;
|
||||
|
||||
struct nf_conn *master = ct->master;
|
||||
@@ -446,12 +446,13 @@ static void expected(struct nf_conn* ct,
|
||||
pr_debug("newsrcip=%pI4, newdstip=%pI4, newip=%pI4\n",
|
||||
&newsrcip, &newdstip, &newip);
|
||||
|
||||
- mr.rangesize = 1;
|
||||
+ memset(&nr, 0, sizeof(nr));
|
||||
+
|
||||
// We don't want to manip the per-protocol, just the IPs.
|
||||
- mr.range[0].flags = NF_NAT_RANGE_MAP_IPS;
|
||||
- mr.range[0].min_ip = mr.range[0].max_ip = newip;
|
||||
+ nr.flags = NF_NAT_RANGE_MAP_IPS;
|
||||
+ nr.min_addr.ip = nr.max_addr.ip = newip;
|
||||
|
||||
- nf_nat_setup_info(ct, &mr.range[0], NF_NAT_MANIP_DST);
|
||||
+ nf_nat_setup_info(ct, &nr, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in a new issue