diff options
Diffstat (limited to 'package/rtsp')
-rw-r--r-- | package/rtsp/Makefile | 39 | ||||
-rw-r--r-- | package/rtsp/src/Makefile | 24 | ||||
-rw-r--r-- | package/rtsp/src/README.rst | 40 | ||||
-rw-r--r-- | package/rtsp/src/netfilter_helpers.h | 133 | ||||
-rw-r--r-- | package/rtsp/src/netfilter_mime.h | 89 | ||||
-rw-r--r-- | package/rtsp/src/nf_conntrack_rtsp.c | 521 | ||||
-rw-r--r-- | package/rtsp/src/nf_conntrack_rtsp.h | 64 | ||||
-rw-r--r-- | package/rtsp/src/nf_nat_rtsp.c | 488 |
8 files changed, 0 insertions, 1398 deletions
diff --git a/package/rtsp/Makefile b/package/rtsp/Makefile deleted file mode 100644 index 4078ab9eb..000000000 --- a/package/rtsp/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# This file is part of the OpenADK project. OpenADK is copyrighted -# material, please see the LICENCE file in the top-level directory. - -include ${TOPDIR}/rules.mk - -PKG_NAME:= rtsp -PKG_VERSION:= 1.0 -PKG_RELEASE:= 1 -PKG_MD5SUM:= 92bb09883dd8a77ec5cfbff1c8932b15 -PKG_DESCR:= connection tracking for RTSP -PKG_SECTION:= kernel -PKG_DEPENDS:= kmod-ip-nf-iptables kmod-nf-conntrack -PKG_URL:= http://github.com/maru-sama/rtsp-linux-v2.6 - -PKG_CFLINE_RTSP:= depends on !ADK_TOOLCHAIN_ONLY -PKG_ARCH_DEPENDS:= !arm - -NO_DISTFILES:= 1 - -include ${TOPDIR}/mk/package.mk - -$(eval $(call PKG_template,RTSP_KMOD,rtsp-kmod,${KERNEL_VERSION}-${ADK_TARGET}-${PKG_RELEASE},,${PKG_DESCR},${PKG_SECTION})) - -CONFIG_STYLE:= manual -BUILD_STYLE:= manual -INSTALL_STYLE:= manual - -pre-build: - $(MAKE) -C ${WRKBUILD} $(KERNEL_MODULE_FLAGS) all - -do-install: - ${INSTALL_DIR} ${IDIR_RTSP_KMOD}/etc/modules.d/ - echo "nf_conntrack_rtsp" > ${IDIR_RTSP_KMOD}/etc/modules.d/60-nf-nat-rtsp - echo "nf_nat_rtsp" >> ${IDIR_RTSP_KMOD}/etc/modules.d/60-nf-nat-rtsp - ${INSTALL_DIR} ${IDIR_RTSP_KMOD}/lib/modules/${KERNEL_VERSION}/ - ${INSTALL_DATA} ${WRKBUILD}/*.ko \ - ${IDIR_RTSP_KMOD}/lib/modules/${KERNEL_VERSION} - -include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/rtsp/src/Makefile b/package/rtsp/src/Makefile deleted file mode 100644 index d7be5bab8..000000000 --- a/package/rtsp/src/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -ifneq ($(KERNELRELEASE),) -# kbuild part of makefile -ifndef CONFIG_NF_CONNTRACK -$(error ** You need to enable NF_CONNTRACK in your kernel **) -endif - -obj-m := nf_conntrack_rtsp.o nf_nat_rtsp.o -else - -# Normal Makefile - -all: - $(MAKE) -C $(KERNELDIR) M=`pwd` modules - -debug: - $(MAKE) -C $(KERNELDIR) EXTRA_CFLAGS=-DDEBUG M=`pwd` modules - -modules_install: - $(MAKE) -C $(KERNELDIR) M=`pwd` modules_install - -clean: - rm -rf *.o *.ko *.mod.c .*.cmd Module.symvers modules.order .tmp_versions - -endif diff --git a/package/rtsp/src/README.rst b/package/rtsp/src/README.rst deleted file mode 100644 index dd20fe072..000000000 --- a/package/rtsp/src/README.rst +++ /dev/null @@ -1,40 +0,0 @@ -Disclaimer: -=========== - -This software is provided as is. I take no responsibility if it destroys your -data or opens up a security hole on your firewall. That said, I have yet to -hear something about this happening. - -I did not create this code myself, most was written by Tom Marshall, later on -Harald Welte and then Steven van Acker ported it to the new 2.6 netfilter API. -I just picked up this code in 2007 and made it compile and hopefully work with -the new changed netfilter API. - -Bugs: -===== - -Of course there are. One of the most important ones, is that you MUST NOT -filter outgoing connections otherwise the reply packes go missing. I tried to -figure out, why the _expect call is not taking care of the outgoing connections -but I was not able to figure this out. I gladly welcome patches that fix this -and other bugs. - -Build Instructions: -=================== - -Have the kernel source ready in some place and NF_CONNTRACK_NAT enabled in the -configuration otherwise you will get an error during make. The Kbuild setup -looks in /lib/modules/\`uname -r\`/build for the source. - -If the source is located in another place set the KERNELDIR environment -variable accordingly. - -After that a: - - * make - * make modules_install (as root) - -should be enough. -Then do a "modprobe nf_nat_rtsp" as root and try to connect to a RTSP -service. - diff --git a/package/rtsp/src/netfilter_helpers.h b/package/rtsp/src/netfilter_helpers.h deleted file mode 100644 index 903f37455..000000000 --- a/package/rtsp/src/netfilter_helpers.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Helpers for netfiler modules. This file provides implementations for basic - * functions such as strncasecmp(), etc. - * - * gcc will warn for defined but unused functions, so we only include the - * functions requested. The following macros are used: - * NF_NEED_STRNCASECMP nf_strncasecmp() - * NF_NEED_STRTOU16 nf_strtou16() - * NF_NEED_STRTOU32 nf_strtou32() - */ -#ifndef _NETFILTER_HELPERS_H -#define _NETFILTER_HELPERS_H - -/* Only include these functions for kernel code. */ -#ifdef __KERNEL__ - -#include <linux/ctype.h> -#define iseol(c) ( (c) == '\r' || (c) == '\n' ) - -/* - * The standard strncasecmp() - */ -#ifdef NF_NEED_STRNCASECMP -static int -nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) -{ - if (s1 == NULL || s2 == NULL) - { - if (s1 == NULL && s2 == NULL) - { - return 0; - } - return (s1 == NULL) ? -1 : 1; - } - while (len > 0 && tolower(*s1) == tolower(*s2)) - { - len--; - s1++; - s2++; - } - return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); -} -#endif /* NF_NEED_STRNCASECMP */ - -/* - * Parse a string containing a 16-bit unsigned integer. - * Returns the number of chars used, or zero if no number is found. - */ -#ifdef NF_NEED_STRTOU16 -static int -nf_strtou16(const char* pbuf, u_int16_t* pval) -{ - int n = 0; - - *pval = 0; - while (isdigit(pbuf[n])) - { - *pval = (*pval * 10) + (pbuf[n] - '0'); - n++; - } - - return n; -} -#endif /* NF_NEED_STRTOU16 */ - -/* - * Parse a string containing a 32-bit unsigned integer. - * Returns the number of chars used, or zero if no number is found. - */ -#ifdef NF_NEED_STRTOU32 -static int -nf_strtou32(const char* pbuf, u_int32_t* pval) -{ - int n = 0; - - *pval = 0; - while (pbuf[n] >= '0' && pbuf[n] <= '9') - { - *pval = (*pval * 10) + (pbuf[n] - '0'); - n++; - } - - return n; -} -#endif /* NF_NEED_STRTOU32 */ - -/* - * Given a buffer and length, advance to the next line and mark the current - * line. - */ -#ifdef NF_NEED_NEXTLINE -static int -nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -{ - uint off = *poff; - uint physlen = 0; - - if (off >= len) - { - return 0; - } - - while (p[off] != '\n') - { - if (len-off <= 1) - { - return 0; - } - - physlen++; - off++; - } - - /* if we saw a crlf, physlen needs adjusted */ - if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') - { - physlen--; - } - - /* advance past the newline */ - off++; - - *plineoff = *poff; - *plinelen = physlen; - *poff = off; - - return 1; -} -#endif /* NF_NEED_NEXTLINE */ - -#endif /* __KERNEL__ */ - -#endif /* _NETFILTER_HELPERS_H */ diff --git a/package/rtsp/src/netfilter_mime.h b/package/rtsp/src/netfilter_mime.h deleted file mode 100644 index 7eeb18352..000000000 --- a/package/rtsp/src/netfilter_mime.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * MIME functions for netfilter modules. This file provides implementations - * for basic MIME parsing. MIME headers are used in many protocols, such as - * HTTP, RTSP, SIP, etc. - * - * gcc will warn for defined but unused functions, so we only include the - * functions requested. The following macros are used: - * NF_NEED_MIME_NEXTLINE nf_mime_nextline() - */ -#ifndef _NETFILTER_MIME_H -#define _NETFILTER_MIME_H - -/* Only include these functions for kernel code. */ -#ifdef __KERNEL__ - -#include <linux/ctype.h> - -/* - * Given a buffer and length, advance to the next line and mark the current - * line. If the current line is empty, *plinelen will be set to zero. If - * not, it will be set to the actual line length (including CRLF). - * - * 'line' in this context means logical line (includes LWS continuations). - * Returns 1 on success, 0 on failure. - */ -#ifdef NF_NEED_MIME_NEXTLINE -static int -nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -{ - uint off = *poff; - uint physlen = 0; - int is_first_line = 1; - - if (off >= len) - { - return 0; - } - - do - { - while (p[off] != '\n') - { - if (len-off <= 1) - { - return 0; - } - - physlen++; - off++; - } - - /* if we saw a crlf, physlen needs adjusted */ - if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') - { - physlen--; - } - - /* advance past the newline */ - off++; - - /* check for an empty line */ - if (physlen == 0) - { - break; - } - - /* check for colon on the first physical line */ - if (is_first_line) - { - is_first_line = 0; - if (memchr(p+(*poff), ':', physlen) == NULL) - { - return 0; - } - } - } - while (p[off] == ' ' || p[off] == '\t'); - - *plineoff = *poff; - *plinelen = (physlen == 0) ? 0 : (off - *poff); - *poff = off; - - return 1; -} -#endif /* NF_NEED_MIME_NEXTLINE */ - -#endif /* __KERNEL__ */ - -#endif /* _NETFILTER_MIME_H */ diff --git a/package/rtsp/src/nf_conntrack_rtsp.c b/package/rtsp/src/nf_conntrack_rtsp.c deleted file mode 100644 index f165ea0c9..000000000 --- a/package/rtsp/src/nf_conntrack_rtsp.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - * RTSP extension for IP connection tracking - * (C) 2003 by Tom Marshall <tmarshall at real.com> - * based on ip_conntrack_irc.c - * - * This program is free software; you can redistribute it and/or - * 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. - * - * Module load syntax: - * insmod nf_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS> - * max_outstanding=n setup_timeout=secs - * - * If no ports are specified, the default will be port 554. - * - * With max_outstanding you can define the maximum number of not yet - * answered SETUP requests per RTSP session (default 8). - * 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> -#include <linux/netfilter.h> -#include <linux/ip.h> -#include <linux/inet.h> -#include <net/tcp.h> - -#include <net/netfilter/nf_conntrack.h> -#include <net/netfilter/nf_conntrack_expect.h> -#include <net/netfilter/nf_conntrack_helper.h> -#include "nf_conntrack_rtsp.h" - -#define NF_NEED_STRNCASECMP -#define NF_NEED_STRTOU16 -#define NF_NEED_STRTOU32 -#define NF_NEED_NEXTLINE -#include "netfilter_helpers.h" -#define NF_NEED_MIME_NEXTLINE -#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]; -static int num_ports = 0; -static int max_outstanding = 8; -static unsigned int setup_timeout = 300; - -MODULE_AUTHOR("Tom Marshall <tmarshall at real.com>"); -MODULE_DESCRIPTION("RTSP connection tracking module"); -MODULE_LICENSE("GPL"); -module_param_array(ports, int, &num_ports, 0400); -MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); -module_param(max_outstanding, int, 0400); -MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); -module_param(setup_timeout, int, 0400); -MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); - -static char *rtsp_buffer; -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, - 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); - -EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); - -/* - * Max mappings we will allow for one RTSP connection (for RTP, the number - * of allocated ports is twice this value). Note that SMIL burns a lot of - * ports so keep this reasonably high. If this is too low, you will see a - * lot of "no free client map entries" messages. - */ -#define MAX_PORT_MAPS 16 - -/*** default port list was here in the masq code: 554, 3030, 4040 ***/ - -#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } - -/* - * Parse an RTSP packet. - * - * Returns zero if parsing failed. - * - * Parameters: - * IN ptcp tcp data pointer - * IN tcplen tcp data len - * IN/OUT ptcpoff points to current tcp offset - * OUT phdrsoff set to offset of rtsp headers - * OUT phdrslen set to length of rtsp headers - * OUT pcseqoff set to offset of CSeq header - * OUT pcseqlen set to length of CSeq header - */ -static int -rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, - uint* phdrsoff, uint* phdrslen, - uint* pcseqoff, uint* pcseqlen, - uint* transoff, uint* translen) -{ - uint entitylen = 0; - uint lineoff; - uint linelen; - - if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) - return 0; - - *phdrsoff = *ptcpoff; - while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) { - if (linelen == 0) { - if (entitylen > 0) - *ptcpoff += min(entitylen, tcplen - *ptcpoff); - break; - } - if (lineoff+linelen > tcplen) { - pr_info("!! overrun !!\n"); - break; - } - - if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { - *pcseqoff = lineoff; - *pcseqlen = linelen; - } - - if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { - *transoff = lineoff; - *translen = linelen; - } - - if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) { - uint off = lineoff+15; - SKIP_WSPACE(ptcp+lineoff, linelen, off); - nf_strtou32(ptcp+off, &entitylen); - } - } - *phdrslen = (*ptcpoff) - (*phdrsoff); - - return 1; -} - -/* - * Find lo/hi client ports (if any) in transport header - * In: - * ptcp, tcplen = packet - * tranoff, tranlen = buffer to search - * - * Out: - * pport_lo, pport_hi = lo/hi ports (host endian) - * - * Returns nonzero if any client ports found - * - * Note: it is valid (and expected) for the client to request multiple - * transports, so we need to parse the entire line. - */ -static int -rtsp_parse_transport(char* ptran, uint tranlen, - struct ip_ct_rtsp_expect* prtspexp) -{ - int rc = 0; - uint off = 0; - - if (tranlen < 10 || !iseol(ptran[tranlen-1]) || - nf_strncasecmp(ptran, "Transport:", 10) != 0) { - pr_info("sanity check failed\n"); - return 0; - } - - pr_debug("tran='%.*s'\n", (int)tranlen, ptran); - off += 10; - SKIP_WSPACE(ptran, tranlen, off); - - /* Transport: tran;field;field=val,tran;field;field=val,... */ - while (off < tranlen) { - const char* pparamend; - uint nextparamoff; - - pparamend = memchr(ptran+off, ',', tranlen-off); - pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; - nextparamoff = pparamend-ptran; - - 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) { - u_int16_t port; - uint numlen; - - off += 12; - numlen = nf_strtou16(ptran+off, &port); - off += numlen; - if (prtspexp->loport != 0 && prtspexp->loport != port) - pr_debug("multiple ports found, port %hu ignored\n", port); - else { - pr_debug("lo port found : %hu\n", port); - prtspexp->loport = prtspexp->hiport = port; - if (ptran[off] == '-') { - off++; - numlen = nf_strtou16(ptran+off, &port); - off += numlen; - prtspexp->pbtype = pb_range; - prtspexp->hiport = port; - - // If we have a range, assume rtp: - // loport must be even, hiport must be loport+1 - if ((prtspexp->loport & 0x0001) != 0 || - prtspexp->hiport != prtspexp->loport+1) { - pr_debug("incorrect range: %hu-%hu, correcting\n", - prtspexp->loport, prtspexp->hiport); - prtspexp->loport &= 0xfffe; - prtspexp->hiport = prtspexp->loport+1; - } - } else if (ptran[off] == '/') { - off++; - numlen = nf_strtou16(ptran+off, &port); - off += numlen; - prtspexp->pbtype = pb_discon; - prtspexp->hiport = port; - } - rc = 1; - } - } - - /* - * Note we don't look for the destination parameter here. - * If we are using NAT, the NAT module will handle it. If not, - * and the client is sending packets elsewhere, the expectation - * will quietly time out. - */ - - off = nextfieldoff; - } - - off = nextparamoff; - } - - 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 ***/ - -/* outbound packet: client->server */ - -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, - unsigned int protoff) -{ - struct ip_ct_rtsp_expect expinfo; - - int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ - //struct tcphdr* tcph = (void*)iph + iph->ihl * 4; - //uint tcplen = pktlen - iph->ihl * 4; - char* pdata = rb_ptr; - //uint datalen = tcplen - tcph->doff * 4; - uint dataoff = 0; - int ret = NF_ACCEPT; - - struct nf_conntrack_expect *exp; - - __be16 be_loport; - - typeof(nf_nat_rtsp_hook) nf_nat_rtsp; - - memset(&expinfo, 0, sizeof(expinfo)); - - while (dataoff < datalen) { - uint cmdoff = dataoff; - uint hdrsoff = 0; - uint hdrslen = 0; - uint cseqoff = 0; - uint cseqlen = 0; - uint transoff = 0; - uint translen = 0; - uint off; - - if (!rtsp_parse_message(pdata, datalen, &dataoff, - &hdrsoff, &hdrslen, - &cseqoff, &cseqlen, - &transoff, &translen)) - break; /* not a valid message */ - - if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) - continue; /* not a SETUP message */ - pr_debug("found a setup message\n"); - - off = 0; - if(translen) { - rtsp_parse_transport(pdata+transoff, translen, &expinfo); - } - - if (expinfo.loport == 0) { - pr_debug("no udp transports found\n"); - continue; /* no udp transports found */ - } - - 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) { - 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, - IPPROTO_UDP, NULL, &be_loport); - - exp->master = ct; - - exp->expectfn = expected; - 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("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)); - - 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, protoff, hdrsoff, hdrslen, &expinfo, exp); - else if (nf_ct_expect_related(exp) != 0) { - pr_info("nf_conntrack_expect_related failed\n"); - ret = NF_DROP; - } - nf_ct_expect_put(exp); - goto out; - } -out: - - return ret; -} - - -static inline int -help_in(struct sk_buff *skb, size_t pktlen, - struct nf_conn* ct, enum ip_conntrack_info ctinfo) -{ - return NF_ACCEPT; -} - -static int help(struct sk_buff *skb, unsigned int protoff, - struct nf_conn *ct, enum ip_conntrack_info ctinfo) -{ - struct tcphdr _tcph, *th; - unsigned int dataoff, datalen; - char *rb_ptr; - int ret = NF_DROP; - - /* Until there's been traffic both ways, don't look in packets. */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { - pr_debug("conntrackinfo = %u\n", ctinfo); - return NF_ACCEPT; - } - - /* Not whole TCP header? */ - th = skb_header_pointer(skb,protoff, sizeof(_tcph), &_tcph); - - if (!th) - return NF_ACCEPT; - - /* No data ? */ - dataoff = protoff + th->doff*4; - datalen = skb->len - dataoff; - if (dataoff >= skb->len) - return NF_ACCEPT; - - spin_lock_bh(&rtsp_buffer_lock); - rb_ptr = skb_header_pointer(skb, dataoff, - skb->len - dataoff, rtsp_buffer); - BUG_ON(rb_ptr == NULL); - -#if 0 - /* Checksum invalid? Ignore. */ - /* FIXME: Source route IP option packets --RR */ - if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, - csum_partial((char*)tcph, tcplen, 0))) - { - DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", - tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); - return NF_ACCEPT; - } -#endif - - switch (CTINFO2DIR(ctinfo)) { - case IP_CT_DIR_ORIGINAL: - ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff); - break; - case IP_CT_DIR_REPLY: - pr_debug("IP_CT_DIR_REPLY\n"); - /* inbound packet: server->client */ - ret = NF_ACCEPT; - break; - } - - spin_unlock_bh(&rtsp_buffer_lock); - - return ret; -} - -static struct nf_conntrack_helper rtsp_helpers[MAX_PORTS]; -static char rtsp_names[MAX_PORTS][10]; - -/* This function is intentionally _NOT_ defined as __exit */ -static void -fini(void) -{ - int i; - for (i = 0; i < num_ports; i++) { - pr_debug("unregistering port %d\n", ports[i]); - nf_conntrack_helper_unregister(&rtsp_helpers[i]); - } - kfree(rtsp_buffer); -} - -static int __init -init(void) -{ - int i, ret; - struct nf_conntrack_helper *hlpr; - char *tmpname; - - printk("nf_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); - - if (max_outstanding < 1) { - printk("nf_conntrack_rtsp: max_outstanding must be a positive integer\n"); - return -EBUSY; - } - if (setup_timeout < 0) { - printk("nf_conntrack_rtsp: setup_timeout must be a positive integer\n"); - return -EBUSY; - } - - rtsp_exp_policy.max_expected = max_outstanding; - rtsp_exp_policy.timeout = setup_timeout; - - rtsp_buffer = kmalloc(65536, GFP_KERNEL); - if (!rtsp_buffer) - return -ENOMEM; - - /* If no port given, default to standard rtsp port */ - if (ports[0] == 0) { - ports[0] = RTSP_PORT; - } - - for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { - hlpr = &rtsp_helpers[i]; - memset(hlpr, 0, sizeof(struct nf_conntrack_helper)); - 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; - - tmpname = &rtsp_names[i][0]; - if (ports[i] == RTSP_PORT) { - sprintf(tmpname, "rtsp"); - } else { - sprintf(tmpname, "rtsp-%d", i); - } - strlcpy(hlpr->name, tmpname, sizeof(hlpr->name)); - - pr_debug("port #%d: %d\n", i, ports[i]); - - ret = nf_conntrack_helper_register(hlpr); - - if (ret) { - printk("nf_conntrack_rtsp: ERROR registering port %d\n", ports[i]); - fini(); - return -EBUSY; - } - num_ports++; - } - return 0; -} - -module_init(init); -module_exit(fini); - -EXPORT_SYMBOL(nf_nat_rtsp_hook_expectfn); - diff --git a/package/rtsp/src/nf_conntrack_rtsp.h b/package/rtsp/src/nf_conntrack_rtsp.h deleted file mode 100644 index 356fb4419..000000000 --- a/package/rtsp/src/nf_conntrack_rtsp.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * RTSP extension for IP connection tracking. - * (C) 2003 by Tom Marshall <tmarshall at real.com> - * based on ip_conntrack_irc.h - * - * This program is free software; you can redistribute it and/or - * 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. - */ -#ifndef _IP_CONNTRACK_RTSP_H -#define _IP_CONNTRACK_RTSP_H - -//#define IP_NF_RTSP_DEBUG 1 -#define IP_NF_RTSP_VERSION "0.6.21" - -#ifdef __KERNEL__ -/* port block types */ -typedef enum { - pb_single, /* client_port=x */ - pb_range, /* client_port=x-y */ - pb_discon /* client_port=x/y (rtspbis) */ -} portblock_t; - -/* We record seq number and length of rtsp headers here, all in host order. */ - -/* - * This structure is per expected connection. It is a member of struct - * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored - * there and we are expected to only store the length of the data which - * needs replaced. If a packet contains multiple RTSP messages, we create - * one expected connection per message. - * - * We use these variables to mark the entire header block. This may seem - * like overkill, but the nature of RTSP requires it. A header may appear - * multiple times in a message. We must treat two Transport headers the - * same as one Transport header with two entries. - */ -struct ip_ct_rtsp_expect -{ - u_int32_t len; /* length of header block */ - portblock_t pbtype; /* Type of port block that was requested */ - u_int16_t loport; /* Port that was requested, low or first */ - u_int16_t hiport; /* Port that was requested, high or second */ -#if 0 - uint method; /* RTSP method */ - uint cseq; /* CSeq from request */ -#endif -}; - -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); - -extern void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); - -#define RTSP_PORT 554 - -#endif /* __KERNEL__ */ - -#endif /* _IP_CONNTRACK_RTSP_H */ diff --git a/package/rtsp/src/nf_nat_rtsp.c b/package/rtsp/src/nf_nat_rtsp.c deleted file mode 100644 index bb06b4502..000000000 --- a/package/rtsp/src/nf_nat_rtsp.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * RTSP extension for TCP NAT alteration - * (C) 2003 by Tom Marshall <tmarshall at real.com> - * based on ip_nat_irc.c - * - * This program is free software; you can redistribute it and/or - * 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. - * - * Module load syntax: - * insmod nf_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS> - * stunaddr=<address> - * destaction=[auto|strip|none] - * - * If no ports are specified, the default will be port 554 only. - * - * stunaddr specifies the address used to detect that a client is using STUN. - * If this address is seen in the destination parameter, it is assumed that - * the client has already punched a UDP hole in the firewall, so we don't - * mangle the client_port. If none is specified, it is autodetected. It - * only needs to be set if you have multiple levels of NAT. It should be - * set to the external address that the STUN clients detect. Note that in - * this case, it will not be possible for clients to use UDP with servers - * between the NATs. - * - * If no destaction is specified, auto is used. - * destaction=auto: strip destination parameter if it is not stunaddr. - * destaction=strip: always strip destination parameter (not recommended). - * destaction=none: do not touch destination parameter (not recommended). - */ - -#include <linux/module.h> -#include <net/tcp.h> -#include <net/netfilter/nf_nat.h> -#include <net/netfilter/nf_nat_helper.h> -#include "nf_conntrack_rtsp.h" -#include <net/netfilter/nf_conntrack_expect.h> - -#include <linux/inet.h> -#include <linux/ctype.h> -#define NF_NEED_STRNCASECMP -#define NF_NEED_STRTOU16 -#include "netfilter_helpers.h" -#define NF_NEED_MIME_NEXTLINE -#include "netfilter_mime.h" - -#define MAX_PORTS 8 -#define DSTACT_AUTO 0 -#define DSTACT_STRIP 1 -#define DSTACT_NONE 2 - -static char* stunaddr = NULL; -static char* destaction = NULL; - -static u_int32_t extip = 0; -static int dstact = 0; - -MODULE_AUTHOR("Tom Marshall <tmarshall at real.com>"); -MODULE_DESCRIPTION("RTSP network address translation module"); -MODULE_LICENSE("GPL"); -module_param(stunaddr, charp, 0644); -MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); -module_param(destaction, charp, 0644); -MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); - -#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } - -/*** helper functions ***/ - -static void -get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) -{ - struct iphdr* iph = ip_hdr(skb); - struct tcphdr* tcph = (void *)iph + ip_hdrlen(skb); - - *pptcpdata = (char*)tcph + tcph->doff*4; - *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; -} - -/*** nat functions ***/ - -/* - * Mangle the "Transport:" header: - * - Replace all occurences of "client_port=<spec>" - * - Handle destination parameter - * - * In: - * ct, ctinfo = conntrack context - * skb = packet - * tranoff = Transport header offset from TCP data - * tranlen = Transport header length (incl. CRLF) - * rport_lo = replacement low port (host endian) - * rport_hi = replacement high port (host endian) - * - * Returns packet size difference. - * - * Assumes that a complete transport header is present, ending with CR or LF - */ -static int -rtsp_mangle_tran(enum ip_conntrack_info ctinfo, unsigned int protoff, - struct nf_conntrack_expect* exp, - struct ip_ct_rtsp_expect* prtspexp, - struct sk_buff* skb, uint tranoff, uint tranlen) -{ - char* ptcp; - uint tcplen; - char* ptran; - char rbuf1[16]; /* Replacement buffer (one port) */ - uint rbuf1len; /* Replacement len (one port) */ - char rbufa[16]; /* Replacement buffer (all ports) */ - uint rbufalen; /* Replacement len (all ports) */ - u_int32_t newip; - 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; - - char szextaddr[15+1]; - uint extaddrlen; - int is_stun; - - get_skb_tcpdata(skb, &ptcp, &tcplen); - ptran = ptcp+tranoff; - - if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || - tranlen < 10 || !iseol(ptran[tranlen-1]) || - nf_strncasecmp(ptran, "Transport:", 10) != 0) - { - pr_info("sanity check failed\n"); - return 0; - } - off += 10; - SKIP_WSPACE(ptcp+tranoff, tranlen, off); - - newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; - t = &exp->tuple; - t->dst.u3.ip = newip; - - extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) - : sprintf(szextaddr, "%pI4", &newip); - pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); - - rbuf1len = rbufalen = 0; - 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) - { - pr_debug("using port %hu\n", loport); - break; - } - } - 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); - break; - } - } - if (loport != 0) - { - rbuf1len = sprintf(rbuf1, "%hu", loport); - rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1); - } - 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) - { - 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) - { - pr_debug("using port %hu (2 of 2)\n", hiport); - break; - } - } - 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); - } - } - break; - } - - if (rbuf1len == 0) - { - return 0; /* cannot get replacement port(s) */ - } - - /* Transport: tran;field;field=val,tran;field;field=val,... */ - 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; - - /* - * We pass over each param twice. On the first pass, we look for a - * destination= field. It is handled by the security policy. If it - * is present, allowed, and equal to our external address, we assume - * that STUN is being used and we leave the client_port= field alone. - */ - is_stun = 0; - saveoff = off; - 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 (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) - { - is_stun = 1; - } - if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) - { - diff = nextfieldoff-off; - if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, - off, diff, NULL, 0)) - { - /* mangle failed, all we can do is bail */ - nf_ct_unexpect_related(exp); - return 0; - } - get_skb_tcpdata(skb, &ptcp, &tcplen); - ptran = ptcp+tranoff; - tranlen -= diff; - nextparamoff -= diff; - nextfieldoff -= diff; - } - } - - off = nextfieldoff; - } - if (is_stun) - { - continue; - } - off = saveoff; - 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) - { - u_int16_t port; - uint numlen; - uint origoff; - uint origlen; - char* rbuf = rbuf1; - uint rbuflen = rbuf1len; - - off += 12; - origoff = (ptran-ptcp)+off; - origlen = 0; - numlen = nf_strtou16(ptran+off, &port); - off += numlen; - origlen += numlen; - if (port != prtspexp->loport) - { - pr_debug("multiple ports found, port %hu ignored\n", port); - } - else - { - if (ptran[off] == '-' || ptran[off] == '/') - { - off++; - origlen++; - numlen = nf_strtou16(ptran+off, &port); - off += numlen; - origlen += numlen; - rbuf = rbufa; - rbuflen = rbufalen; - } - - /* - * note we cannot just memcpy() if the sizes are the same. - * the mangle function does skb resizing, checks for a - * cloned skb, and updates the checksums. - * - * parameter 4 below is offset from start of tcp data. - */ - diff = origlen-rbuflen; - if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, - origoff, origlen, rbuf, rbuflen)) - { - /* mangle failed, all we can do is bail */ - nf_ct_unexpect_related(exp); - return 0; - } - get_skb_tcpdata(skb, &ptcp, &tcplen); - ptran = ptcp+tranoff; - tranlen -= diff; - nextparamoff -= diff; - nextfieldoff -= diff; - } - } - - off = nextfieldoff; - } - - off = nextparamoff; - } - - return 1; -} - -static uint -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) -{ - char* ptcp; - uint tcplen; - uint hdrsoff; - uint hdrslen; - uint lineoff; - uint linelen; - uint off; - - //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; - //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); - - get_skb_tcpdata(skb, &ptcp, &tcplen); - hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); - hdrslen = matchlen; - off = hdrsoff; - pr_debug("NAT rtsp help_out\n"); - - while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) - { - if (linelen == 0) - { - break; - } - 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) - { - uint oldtcplen = tcplen; - pr_debug("hdr: Transport\n"); - if (!rtsp_mangle_tran(ctinfo, protoff, exp, prtspexp, skb, lineoff, linelen)) - { - pr_debug("hdr: Transport mangle failed"); - break; - } - get_skb_tcpdata(skb, &ptcp, &tcplen); - hdrslen -= (oldtcplen-tcplen); - off -= (oldtcplen-tcplen); - lineoff -= (oldtcplen-tcplen); - linelen -= (oldtcplen-tcplen); - pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); - } - } - - return NF_ACCEPT; -} - -static unsigned int -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) -{ - int dir = CTINFO2DIR(ctinfo); - int rc = NF_ACCEPT; - - switch (dir) - { - case IP_CT_DIR_ORIGINAL: - rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, exp); - break; - case IP_CT_DIR_REPLY: - pr_debug("unmangle ! %u\n", ctinfo); - /* XXX: unmangle */ - rc = NF_ACCEPT; - break; - } - //UNLOCK_BH(&ip_rtsp_lock); - - return rc; -} - -static void expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) -{ - struct nf_nat_range range; - union nf_inet_addr newdstip, newsrcip, newip; - - struct nf_conn *master = ct->master; - - newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3; - newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3; - //FIXME (how to port that ?) - //code from 2.4 : newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip; - newip = newdstip; - - pr_debug("newsrcip=%pI4, newdstip=%pI4, newip=%pI4\n", - &newsrcip.ip, &newdstip.ip, &newip.ip); - - // We don't want to manip the per-protocol, just the IPs. - range.flags = NF_NAT_RANGE_MAP_IPS; - range.min_addr = range.max_addr = newip; - - nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); -} - - -static void __exit fini(void) -{ - nf_nat_rtsp_hook = NULL; - nf_nat_rtsp_hook_expectfn = NULL; - synchronize_net(); -} - -static int __init init(void) -{ - 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; - - if (stunaddr != NULL) - extip = in_aton(stunaddr); - - if (destaction != NULL) { - if (strcmp(destaction, "auto") == 0) - dstact = DSTACT_AUTO; - - if (strcmp(destaction, "strip") == 0) - dstact = DSTACT_STRIP; - - if (strcmp(destaction, "none") == 0) - dstact = DSTACT_NONE; - } - - return 0; -} - -module_init(init); -module_exit(fini); |