Browse Source

Merge pull request #5931 from dedeckeh/pr-xtables-addons-rtsp

xtables-addons: rtsp helper improvements
lilik-openwrt-22.03
Hans Dedecker 7 years ago
committed by GitHub
parent
commit
916b2f7cb7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 178 additions and 21 deletions
  1. +1
    -1
      net/xtables-addons/Makefile
  2. +177
    -20
      net/xtables-addons/patches/100-add-rtsp-conntrack.patch

+ 1
- 1
net/xtables-addons/Makefile View File

@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=xtables-addons
PKG_VERSION:=2.14
PKG_RELEASE:=3
PKG_RELEASE:=4
PKG_HASH:=d215a9a8b8e66aae04b982fa2e1228e8a71e7dfe42320df99e34e5000cbdf152
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz


+ 177
- 20
net/xtables-addons/patches/100-add-rtsp-conntrack.patch View File

@ -235,7 +235,7 @@
+#endif /* _NETFILTER_MIME_H */
--- /dev/null
+++ b/extensions/rtsp/nf_conntrack_rtsp.c
@@ -0,0 +1,576 @@
@@ -0,0 +1,732 @@
+/*
+ * RTSP extension for IP connection tracking
+ * (C) 2003 by Tom Marshall <tmarshall at real.com>
@ -250,7 +250,13 @@
+ * 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
+ * - codestyle fixes and other less significant bug fixes
+ * 2018-04-17: Alin Nastac <alin.nastac at gmail.com>
+ * Hans Dedecker <dedeckeh at gmail.com>
+ * - use IP address read from SETUP URI in expected connections
+ * 2018-04-18: Hans Dedecker <dedeckeh at gmail.com>
+ * - update RTP expected connection source IP based on SOURCE
+ * in the SETUP reply message
+ *
+ * based on ip_conntrack_irc.c
+ *
@ -399,13 +405,14 @@
+}
+
+/*
+ * Find lo/hi client ports (if any) in transport header
+ * Find lo/hi client ports and/or source (if any) in transport header
+ * In:
+ * ptcp, tcplen = packet
+ * tranoff, tranlen = buffer to search
+ *
+ * Out:
+ * pport_lo, pport_hi = lo/hi ports (host endian)
+ * srvaddr
+ *
+ * Returns nonzero if any client ports found
+ *
@ -482,6 +489,17 @@
+ }
+ rc = 1;
+ }
+ } else if (strncmp(ptran+off, "source=", 7) == 0) {
+ uint srcaddrlen;
+
+ off += 7;
+ srcaddrlen = nextfieldoff - off - 1;
+
+ if (in4_pton(ptran + off, srcaddrlen,
+ (u8 *)&prtspexp->srvaddr.in,
+ -1, NULL))
+ pr_debug("source found : %pI4\n",
+ &prtspexp->srvaddr.ip);
+ }
+
+ /*
@ -543,6 +561,7 @@
+ uint transoff = 0;
+ uint translen = 0;
+ uint off;
+ union nf_inet_addr srvaddr;
+
+ if (!rtsp_parse_message(pdata, datalen, &dataoff,
+ &hdrsoff, &hdrslen,
@ -559,6 +578,32 @@
+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
+ continue; /* not a SETUP message */
+
+ srvaddr = ct->tuplehash[!dir].tuple.src.u3;
+
+ /* try to get RTP media source from SETUP URI */
+ off = cmdoff + 6;
+ while (off < datalen) {
+ if (strncmp(pdata+off, "://", 3) == 0) {
+ off += 3;
+ cmdoff = off;
+
+ while (off < datalen) {
+ if (pdata[off] == ':' ||
+ pdata[off] == '/' ||
+ pdata[off] == ' ') {
+ in4_pton(pdata + cmdoff,
+ off - cmdoff,
+ (u8 *)&srvaddr.in,
+ -1, NULL);
+ break;
+ }
+ off++;
+ }
+ break;
+ }
+ off++;
+ }
+
+ pr_debug("found a setup message\n");
+
+ off = 0;
@ -583,8 +628,7 @@
+ }
+
+ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT,
+ nf_ct_l3num(ct),
+ NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */
+ nf_ct_l3num(ct), &srvaddr,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &be_loport);
+
@ -601,8 +645,7 @@
+ }
+
+ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT,
+ nf_ct_l3num(ct),
+ NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */
+ nf_ct_l3num(ct), &srvaddr,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &be_hiport);
+
@ -659,11 +702,120 @@
+
+
+static inline int
+help_in(struct sk_buff *skb, size_t pktlen,
+ struct nf_conn* ct, enum ip_conntrack_info ctinfo)
+{
+ return NF_ACCEPT;
+}
+help_in(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;
+ union nf_inet_addr srvaddr;
+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
+ int len;
+ char* pdata = rb_ptr;
+ uint dataoff = 0;
+ int ret = NF_ACCEPT;
+ u_int8_t family;
+ struct nf_conntrack_expect *exp_ct = NULL;
+ struct nf_conntrack_tuple t;
+ struct net *net = nf_ct_net(ct);
+
+ 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;
+
+ if (!rtsp_parse_message(pdata, datalen, &dataoff,
+ &hdrsoff, &hdrslen,
+ &cseqoff, &cseqlen,
+ &transoff, &translen))
+ break; /* not a valid message */
+
+ if (strncmp(pdata+cmdoff, "RTSP/", 5) == 0 && translen) {
+ union nf_inet_addr zeroaddr;
+
+ memset(&zeroaddr, 0, sizeof(zeroaddr));
+
+ if (!rtsp_parse_transport(pdata+transoff, translen, &expinfo))
+ continue;
+
+ srvaddr = expinfo.srvaddr;
+
+ if (nf_inet_addr_cmp(&srvaddr, &ct->tuplehash[dir].tuple.src.u3) ||
+ nf_inet_addr_cmp(&srvaddr, &zeroaddr))
+ continue;
+ } else
+ continue; /* not valid RTSP reply */
+
+ if (expinfo.loport == 0) {
+ pr_debug("no udp transports found\n");
+ continue; /* no udp transports found */
+ }
+
+ family = nf_ct_l3num(ct);
+ if (family == AF_INET)
+ len = 4;
+ else
+ len = 16;
+
+ /* replace rtp expect src addr */
+ t.src.l3num = family;
+ t.dst.protonum = IPPROTO_UDP;
+
+ memcpy(&t.src.u3, &ct->tuplehash[dir].tuple.src.u3, len);
+ if (sizeof(t.src.u3) > len)
+ /* address needs to be cleared for nf_ct_tuple_equal */
+ memset((void *)&t.src.u3 + len, 0, sizeof(t.src.u3) - len);
+
+ t.src.u.all = 0;
+
+ memcpy(&t.dst.u3, &ct->tuplehash[dir].tuple.dst.u3, len);
+ if (sizeof(t.dst.u3) > len)
+ /* address needs to be cleared for nf_ct_tuple_equal */
+ memset((void *)&t.dst.u3 + len, 0, sizeof(t.dst.u3) - len);
+
+ t.dst.u.all = htons(expinfo.loport);
+
+ /* get the rtp expect and replace the srcaddr with RTP server addr */
+ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t);
+ if (exp_ct) {
+ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len);
+ if (sizeof(exp_ct->tuple.src.u3) > len)
+ /* address needs to be cleared for nf_ct_tuple_equal */
+ memset((void *)&exp_ct->tuple.src.u3 + len, 0,
+ sizeof(exp_ct->tuple.src.u3) - len);
+ } else
+ goto out;
+
+ /* replace rtcp expect src addr */
+ if (expinfo.pbtype == pb_range) {
+ t.dst.u.all = htons(expinfo.hiport);
+
+ /* get the rtcp expect and replace the srcaddr with RTP server addr */
+ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t);
+ if (exp_ct) {
+ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len);
+ if (sizeof(exp_ct->tuple.src.u3) > len)
+ /* address needs to be cleared for nf_ct_tuple_equal */
+ memset((void *)&exp_ct->tuple.src.u3 + len, 0,
+ sizeof(exp_ct->tuple.src.u3) - len);
+ } else
+ goto out;
+ }
+
+ goto out;
+ }
+out:
+ return ret;
+ }
+
+static int help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
@ -720,7 +872,11 @@
+ case IP_CT_DIR_REPLY:
+ pr_debug("IP_CT_DIR_REPLY\n");
+ /* inbound packet: server->client */
+ ret = NF_ACCEPT;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo, protoff);
+#else
+ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo);
+#endif
+ break;
+ }
+
@ -814,7 +970,7 @@
+module_exit(fini);
--- /dev/null
+++ b/extensions/rtsp/nf_conntrack_rtsp.h
@@ -0,0 +1,72 @@
@@ -0,0 +1,73 @@
+/*
+ * RTSP extension for IP connection tracking.
+ * (C) 2003 by Tom Marshall <tmarshall at real.com>
@ -861,13 +1017,14 @@
+ */
+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 */
+ 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 */
+ union nf_inet_addr srvaddr; /* src address in SETUP reply */
+#if 0
+ uint method; /* RTSP method */
+ uint cseq; /* CSeq from request */
+ uint method; /* RTSP method */
+ uint cseq; /* CSeq from request */
+#endif
+};
+


Loading…
Cancel
Save