Changeset 43311


Ignore:
Timestamp:
2014-11-19T10:21:12+01:00 (3 years ago)
Author:
blogic
Message:

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@…>

Location:
trunk/package/network/utils/xtables-addons/patches
Files:
2 deleted
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/network/utils/xtables-addons/patches/100-add-rtsp-conntrack.patch

    r42256 r43311  
    236236--- /dev/null 
    237237+++ b/extensions/rtsp/nf_conntrack_rtsp.c 
    238 @@ -0,0 +1,519 @@ 
     238@@ -0,0 +1,576 @@ 
    239239+/* 
    240240+ * RTSP extension for IP connection tracking 
    241241+ * (C) 2003 by Tom Marshall <tmarshall at real.com> 
     242+ * 
     243+ * 2005-02-13: Harald Welte <laforge at netfilter.org> 
     244+ *     - port to 2.6 
     245+ *     - update to recent post-2.6.11 api changes 
     246+ * 2006-09-14: Steven Van Acker <deepstar at singularity.be> 
     247+ *     - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack 
     248+ * 2007-04-18: Michael Guntsche <mike at it-loops.com> 
     249+ *                     - Port to new NF API 
     250+ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd 
     251+ *     - fixed rtcp nat mapping and other port mapping fixes 
     252+ *     - simple TEARDOWN request handling 
     253+ *     - codestyle fixes and other less significant bug fixes  
     254+ * 
    242255+ * based on ip_conntrack_irc.c 
    243256+ * 
     
    258271+ * an expected data channel (default 300 seconds). 
    259272+ * 
    260 + * 2005-02-13: Harald Welte <laforge at netfilter.org> 
    261 + *     - port to 2.6 
    262 + *     - update to recent post-2.6.11 api changes 
    263 + * 2006-09-14: Steven Van Acker <deepstar at singularity.be> 
    264 + *      - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack 
    265 + * 2007-04-18: Michael Guntsche <mike at it-loops.com> 
    266 + *                     - Port to new NF API 
    267273+ */ 
    268274+ 
     
    287293+ 
    288294+#include <linux/ctype.h> 
    289 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */ 
    290295+ 
    291296+#define MAX_PORTS 8 
     
    308313+static DEFINE_SPINLOCK(rtsp_buffer_lock); 
    309314+ 
    310 +static struct nf_conntrack_expect_policy rtsp_exp_policy;  
     315+static struct nf_conntrack_expect_policy rtsp_exp_policy; 
    311316+ 
    312317+unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, 
    313318+                                enum ip_conntrack_info ctinfo, 
    314 +                                unsigned int matchoff, unsigned int matchlen,struct ip_ct_rtsp_expect* prtspexp, 
    315 +                                struct nf_conntrack_expect *exp); 
    316 +void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); 
     319+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     320+                                unsigned int protoff, 
     321+#endif 
     322+                                unsigned int matchoff, unsigned int matchlen, 
     323+                                struct ip_ct_rtsp_expect* prtspexp, 
     324+                                struct nf_conntrack_expect *rtp_exp, 
     325+                                struct nf_conntrack_expect *rtcp_exp); 
    317326+ 
    318327+EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); 
     
    346355+static int 
    347356+rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, 
    348 +                   uint* phdrsoff, uint* phdrslen, 
    349 +                   uint* pcseqoff, uint* pcseqlen, 
    350 +                   uint* transoff, uint* translen) 
    351 +{ 
    352 +       uint    entitylen = 0; 
    353 +       uint    lineoff; 
    354 +       uint    linelen; 
     357+                  uint* phdrsoff, uint* phdrslen, 
     358+                  uint* pcseqoff, uint* pcseqlen, 
     359+                  uint* transoff, uint* translen) 
     360+{ 
     361+       uint    entitylen = 0; 
     362+       uint    lineoff; 
     363+       uint    linelen; 
    355364+        
    356365+       if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) 
     
    368377+                       break; 
    369378+               } 
    370 +                
     379+ 
    371380+               if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { 
    372381+                       *pcseqoff = lineoff; 
     
    406415+static int 
    407416+rtsp_parse_transport(char* ptran, uint tranlen, 
    408 +                     struct ip_ct_rtsp_expect* prtspexp) 
    409 +{ 
    410 +       int     rc = 0; 
    411 +       uint    off = 0; 
     417+                    struct ip_ct_rtsp_expect* prtspexp) 
     418+{ 
     419+       int  rc = 0; 
     420+       uint off = 0; 
    412421+        
    413422+       if (tranlen < 10 || !iseol(ptran[tranlen-1]) || 
     
    440449+                               u_int16_t   port; 
    441450+                               uint        numlen; 
    442 +                    
     451+ 
    443452+                               off += 12; 
    444453+                               numlen = nf_strtou16(ptran+off, &port); 
     
    492501+} 
    493502+ 
    494 +void expected(struct nf_conn *ct, struct nf_conntrack_expect *exp) 
    495 +{ 
    496 +               typeof(nf_nat_rtsp_hook_expectfn) nf_nat_rtsp_expectfn; 
    497 +               nf_nat_rtsp_expectfn = rcu_dereference(nf_nat_rtsp_hook_expectfn); 
    498 +    if(nf_nat_rtsp_expectfn && ct->master->status & IPS_NAT_MASK) { 
    499 +        nf_nat_rtsp_expectfn(ct,exp); 
    500 +    } 
    501 +} 
    502503+ 
    503504+/*** conntrack functions ***/ 
     
    507508+static inline int 
    508509+help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, 
    509 +                struct nf_conn *ct, enum ip_conntrack_info ctinfo) 
     510+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     511+        struct nf_conn *ct, enum ip_conntrack_info ctinfo, 
     512+        unsigned int protoff) 
     513+#else 
     514+        struct nf_conn *ct, enum ip_conntrack_info ctinfo) 
     515+#endif 
    510516+{ 
    511517+       struct ip_ct_rtsp_expect expinfo; 
     
    519525+       int ret = NF_ACCEPT; 
    520526+        
    521 +       struct nf_conntrack_expect *exp; 
     527+       struct nf_conntrack_expect *rtp_exp; 
     528+       struct nf_conntrack_expect *rtcp_exp = NULL; 
    522529+        
    523530+       __be16 be_loport; 
     531+       __be16 be_hiport; 
    524532+        
    525533+       typeof(nf_nat_rtsp_hook) nf_nat_rtsp; 
     
    528536+        
    529537+       while (dataoff < datalen) { 
    530 +               uint    cmdoff = dataoff; 
    531 +               uint    hdrsoff = 0; 
    532 +               uint    hdrslen = 0; 
    533 +               uint    cseqoff = 0; 
    534 +               uint    cseqlen = 0; 
    535 +               uint    transoff = 0; 
    536 +               uint    translen = 0; 
    537 +               uint    off; 
     538+               uint cmdoff = dataoff; 
     539+               uint hdrsoff = 0; 
     540+               uint hdrslen = 0; 
     541+               uint cseqoff = 0; 
     542+               uint cseqlen = 0; 
     543+               uint transoff = 0; 
     544+               uint translen = 0; 
     545+               uint off; 
    538546+                
    539547+               if (!rtsp_parse_message(pdata, datalen, &dataoff, 
     
    542550+                                       &transoff, &translen)) 
    543551+                       break;      /* not a valid message */ 
    544 +                
     552+ 
     553+               if (strncmp(pdata+cmdoff, "TEARDOWN ", 9) == 0) { 
     554+                       pr_debug("teardown handled\n"); 
     555+                       nf_ct_remove_expectations(ct); /* FIXME must be session id aware */ 
     556+                       break; 
     557+               } 
     558+ 
    545559+               if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) 
    546560+                       continue;   /* not a SETUP message */ 
     561+ 
    547562+               pr_debug("found a setup message\n"); 
    548563+ 
    549564+               off = 0; 
    550 +               if(translen) { 
     565+               if(translen) 
    551566+                       rtsp_parse_transport(pdata+transoff, translen, &expinfo); 
    552 +               } 
    553567+ 
    554568+               if (expinfo.loport == 0) { 
     
    558572+ 
    559573+               pr_debug("udp transport found, ports=(%d,%hu,%hu)\n", 
    560 +                      (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); 
    561 + 
    562 +               exp = nf_ct_expect_alloc(ct); 
    563 +               if (!exp) { 
     574+                        (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); 
     575+ 
     576+ 
     577+               be_loport = htons(expinfo.loport); 
     578+ 
     579+               rtp_exp = nf_ct_expect_alloc(ct); 
     580+               if (rtp_exp == NULL) { 
    564581+                       ret = NF_DROP; 
    565582+                       goto out; 
    566583+               } 
    567584+ 
    568 +               be_loport = htons(expinfo.loport); 
    569 + 
    570 +               nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct), 
    571 +                       &ct->tuplehash[!dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3, 
    572 +                       IPPROTO_UDP, NULL, &be_loport);  
    573 + 
    574 +               exp->master = ct; 
    575 + 
    576 +               exp->expectfn = expected; 
    577 +               exp->flags = 0; 
     585+               nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, 
     586+                                 nf_ct_l3num(ct), 
     587+                                 NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */ 
     588+                                 &ct->tuplehash[!dir].tuple.dst.u3, 
     589+                                 IPPROTO_UDP, NULL, &be_loport); 
     590+ 
     591+               rtp_exp->flags = 0; 
    578592+ 
    579593+               if (expinfo.pbtype == pb_range) { 
    580 +                       pr_debug("Changing expectation mask to handle multiple ports\n"); 
    581 +                       //exp->mask.dst.u.udp.port  = 0xfffe; 
    582 +               } 
    583 + 
    584 +               pr_debug("expect_related %pI4:%u-%pI4:%u\n", 
    585 +                      &exp->tuple.src.u3.ip, 
    586 +                      ntohs(exp->tuple.src.u.udp.port), 
    587 +                      &exp->tuple.dst.u3.ip, 
    588 +                      ntohs(exp->tuple.dst.u.udp.port)); 
     594+                       pr_debug("setup expectation for rtcp\n"); 
     595+ 
     596+                       be_hiport = htons(expinfo.hiport); 
     597+                       rtcp_exp = nf_ct_expect_alloc(ct); 
     598+                       if (rtcp_exp == NULL) { 
     599+                               ret = NF_DROP; 
     600+                               goto out1; 
     601+                       } 
     602+ 
     603+                       nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, 
     604+                                         nf_ct_l3num(ct), 
     605+                                         NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */ 
     606+                                         &ct->tuplehash[!dir].tuple.dst.u3, 
     607+                                         IPPROTO_UDP, NULL, &be_hiport); 
     608+ 
     609+                       rtcp_exp->flags = 0; 
     610+ 
     611+                       pr_debug("expect_related %pI4:%u-%u-%pI4:%u-%u\n", 
     612+                                  &rtp_exp->tuple.src.u3.ip, 
     613+                                  ntohs(rtp_exp->tuple.src.u.udp.port), 
     614+                                  ntohs(rtcp_exp->tuple.src.u.udp.port), 
     615+                                  &rtp_exp->tuple.dst.u3.ip, 
     616+                                  ntohs(rtp_exp->tuple.dst.u.udp.port), 
     617+                                  ntohs(rtcp_exp->tuple.dst.u.udp.port)); 
     618+               } else { 
     619+                       pr_debug("expect_related %pI4:%u-%pI4:%u\n", 
     620+                                       &rtp_exp->tuple.src.u3.ip, 
     621+                                       ntohs(rtp_exp->tuple.src.u.udp.port), 
     622+                                       &rtp_exp->tuple.dst.u3.ip, 
     623+                                       ntohs(rtp_exp->tuple.dst.u.udp.port)); 
     624+               } 
    589625+ 
    590626+               nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook); 
    591627+               if (nf_nat_rtsp && ct->status & IPS_NAT_MASK) 
    592628+                       /* pass the request off to the nat helper */ 
    593 +                       ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, &expinfo, exp); 
    594 +               else if (nf_ct_expect_related(exp) != 0) { 
    595 +                       pr_info("nf_conntrack_expect_related failed\n"); 
    596 +                       ret  = NF_DROP; 
    597 +               } 
    598 +               nf_ct_expect_put(exp); 
     629+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     630+                       ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen, 
     631+                                         &expinfo, rtp_exp, rtcp_exp); 
     632+#else 
     633+                       ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, 
     634+                                         &expinfo, rtp_exp, rtcp_exp); 
     635+#endif 
     636+               else { 
     637+                       if (nf_ct_expect_related(rtp_exp) == 0) { 
     638+                               if (rtcp_exp && nf_ct_expect_related(rtcp_exp) != 0) { 
     639+                                       nf_ct_unexpect_related(rtp_exp); 
     640+                                       pr_info("nf_conntrack_expect_related failed for rtcp\n"); 
     641+                                       ret = NF_DROP; 
     642+                               } 
     643+                       } else { 
     644+                               pr_info("nf_conntrack_expect_related failed for rtp\n"); 
     645+                               ret = NF_DROP; 
     646+                       } 
     647+               } 
     648+               if (rtcp_exp) { 
     649+                       nf_ct_expect_put(rtcp_exp); 
     650+               } 
     651+out1: 
     652+               nf_ct_expect_put(rtp_exp); 
    599653+               goto out; 
    600654+       } 
     
    607661+static inline int 
    608662+help_in(struct sk_buff *skb, size_t pktlen, 
    609 + struct nf_conn* ct, enum ip_conntrack_info ctinfo) 
    610 +{ 
    611 + return NF_ACCEPT; 
     663+       struct nf_conn* ct, enum ip_conntrack_info ctinfo) 
     664+{ 
     665+       return NF_ACCEPT; 
    612666+} 
    613667+ 
     
    628682+ 
    629683+       /* Not whole TCP header? */ 
    630 +       th = skb_header_pointer(skb,protoff, sizeof(_tcph), &_tcph); 
     684+       th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); 
    631685+ 
    632686+       if (!th) 
     
    658712+       switch (CTINFO2DIR(ctinfo)) { 
    659713+       case IP_CT_DIR_ORIGINAL: 
     714+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     715+               ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff); 
     716+#else 
    660717+               ret = help_out(skb, rb_ptr, datalen, ct, ctinfo); 
     718+#endif 
    661719+               break; 
    662720+       case IP_CT_DIR_REPLY: 
     
    705763+       } 
    706764+ 
    707 +  rtsp_exp_policy.max_expected = max_outstanding; 
    708 +  rtsp_exp_policy.timeout = setup_timeout; 
     765+       rtsp_exp_policy.max_expected = max_outstanding; 
     766+       rtsp_exp_policy.timeout = setup_timeout; 
    709767+        
    710768+       rtsp_buffer = kmalloc(65536, GFP_KERNEL); 
     
    715773+       if (ports[0] == 0) { 
    716774+               ports[0] = RTSP_PORT; 
     775+               num_ports = 1; 
    717776+       } 
    718777+ 
     
    723782+               hlpr->tuple.src.u.tcp.port = htons(ports[i]); 
    724783+               hlpr->tuple.dst.protonum = IPPROTO_TCP; 
    725 +               //hlpr->mask.src.u.tcp.port = 0xFFFF; 
    726 +               //hlpr->mask.dst.protonum = 0xFF; 
    727784+               hlpr->expect_policy = &rtsp_exp_policy; 
    728785+               hlpr->me = THIS_MODULE; 
     
    735792+                       sprintf(tmpname, "rtsp-%d", i); 
    736793+               } 
     794+ 
     795+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) 
     796+               strlcpy(hlpr->name, tmpname, sizeof(hlpr->name)); 
     797+#else 
    737798+               hlpr->name = tmpname; 
    738 + 
     799+#endif 
    739800+               pr_debug("port #%d: %d\n", i, ports[i]); 
    740801+ 
     
    746807+                       return -EBUSY; 
    747808+               } 
    748 +               num_ports++; 
    749809+       } 
    750810+       return 0; 
     
    753813+module_init(init); 
    754814+module_exit(fini); 
    755 + 
    756 +EXPORT_SYMBOL(nf_nat_rtsp_hook_expectfn); 
    757 + 
    758815--- /dev/null 
    759816+++ b/extensions/rtsp/nf_conntrack_rtsp.h 
    760 @@ -0,0 +1,63 @@ 
     817@@ -0,0 +1,72 @@ 
    761818+/* 
    762819+ * RTSP extension for IP connection tracking. 
     
    768825+ *      as published by the Free Software Foundation; either version 
    769826+ *      2 of the License, or (at your option) any later version. 
    770 + */ 
     827+ * 
     828+ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd 
     829+ *     - conditional compilation for kernel 3.7 
     830+ *     - port mapping improvements 
     831+*/ 
    771832+#ifndef _IP_CONNTRACK_RTSP_H 
    772833+#define _IP_CONNTRACK_RTSP_H 
    773834+ 
     835+#include <linux/version.h> 
     836+ 
    774837+//#define IP_NF_RTSP_DEBUG 1 
    775 +#define IP_NF_RTSP_VERSION "0.6.21" 
     838+#define IP_NF_RTSP_VERSION "0.7" 
    776839+ 
    777840+#ifdef __KERNEL__ 
     
    810873+ 
    811874+extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, 
    812 +                                enum ip_conntrack_info ctinfo, 
    813 +                                unsigned int matchoff, unsigned int matchlen, 
    814 +                                struct ip_ct_rtsp_expect *prtspexp, 
    815 +                                struct nf_conntrack_expect *exp); 
    816 + 
    817 +extern void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); 
     875+                                       enum ip_conntrack_info ctinfo, 
     876+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     877+                                       unsigned int protoff, 
     878+#endif 
     879+                                       unsigned int matchoff, 
     880+                                       unsigned int matchlen, 
     881+                                       struct ip_ct_rtsp_expect *prtspexp, 
     882+                                       struct nf_conntrack_expect *rtp_exp, 
     883+                                       struct nf_conntrack_expect *rtcp_exp); 
    818884+ 
    819885+#define RTSP_PORT   554 
     
    824890--- /dev/null 
    825891+++ b/extensions/rtsp/nf_nat_rtsp.c 
    826 @@ -0,0 +1,491 @@ 
     892@@ -0,0 +1,617 @@ 
    827893+/* 
    828894+ * RTSP extension for TCP NAT alteration 
    829895+ * (C) 2003 by Tom Marshall <tmarshall at real.com> 
     896+ * 
     897+ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd 
     898+ *     - fixed rtcp nat mapping and other port mapping fixes 
     899+ *     - fixed system hard lock because of bug in the parser 
     900+ *     - codestyle fixes and less significant fixes 
     901+ * 
    830902+ * based on ip_nat_irc.c 
    831903+ * 
    832 + *      This program is free software; you can redistribute it and/or 
    833 + *      modify it under the terms of the GNU General Public License 
    834 + *      as published by the Free Software Foundation; either version 
    835 + *      2 of the License, or (at your option) any later version. 
     904+ *     This program is free software; you can redistribute it and/or 
     905+ *     modify it under the terms of the GNU General Public License 
     906+ *     as published by the Free Software Foundation; either version 
     907+ *     2 of the License, or (at your option) any later version. 
    836908+ * 
    837909+ * Module load syntax: 
    838 + *      insmod nf_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS> 
    839 + *                           stunaddr=<address> 
    840 + *                           destaction=[auto|strip|none] 
     910+ *     insmod nf_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS> 
     911+ *                          stunaddr=<address> 
     912+ *                          destaction=[auto|strip|none] 
    841913+ * 
    842914+ * If no ports are specified, the default will be port 554 only. 
     
    858930+ 
    859931+#include <linux/module.h> 
     932+#include <linux/version.h> 
    860933+#include <net/tcp.h> 
     934+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     935+# include <net/netfilter/nf_nat.h> 
     936+#else 
     937+# include <net/netfilter/nf_nat_rule.h> 
     938+#endif 
    861939+#include <net/netfilter/nf_nat_helper.h> 
    862 +#include <net/netfilter/nf_nat_rule.h> 
    863940+#include "nf_conntrack_rtsp.h" 
    864941+#include <net/netfilter/nf_conntrack_expect.h> 
     
    872949+#include "netfilter_mime.h" 
    873950+ 
    874 +#include "../compat_xtables.h" 
    875 + 
    876 +#define MAX_PORTS       8 
    877 +#define DSTACT_AUTO     0 
    878 +#define DSTACT_STRIP    1 
    879 +#define DSTACT_NONE     2 
    880 + 
    881 +static char*    stunaddr = NULL; 
    882 +static char*    destaction = NULL; 
     951+#define MAX_PORTS     8 
     952+#define DSTACT_AUTO   0 
     953+#define DSTACT_STRIP  1 
     954+#define DSTACT_NONE   2 
     955+ 
     956+static char* stunaddr = NULL; 
     957+static char* destaction = NULL; 
    883958+ 
    884959+static u_int32_t extip = 0; 
    885960+static int       dstact = 0; 
     961+ 
     962+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp); 
    886963+ 
    887964+MODULE_AUTHOR("Tom Marshall <tmarshall at real.com>"); 
     
    900977+get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) 
    901978+{ 
    902 +    struct iphdr*   iph  = ip_hdr(skb); 
    903 +    struct tcphdr*  tcph = (void *)iph + ip_hdrlen(skb); 
    904 + 
    905 +    *pptcpdata = (char*)tcph +  tcph->doff*4; 
    906 +    *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; 
    907 +} 
     979+       struct iphdr*   iph  = ip_hdr(skb); 
     980+       struct tcphdr*  tcph = (void *)iph + ip_hdrlen(skb); 
     981+ 
     982+       *pptcpdata = (char*)tcph +  tcph->doff*4; 
     983+       *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; 
     984+} 
     985+ 
     986+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     987+/* copy of sip_sprintf_addr */ 
     988+static int rtsp_sprintf_addr(const struct nf_conn *ct, char *buffer, 
     989+                            const union nf_inet_addr *addr, bool delim) 
     990+{ 
     991+       if (nf_ct_l3num(ct) == NFPROTO_IPV4) { 
     992+               return sprintf(buffer, "%pI4", &addr->ip); 
     993+       } else { 
     994+               if (delim) 
     995+                       return sprintf(buffer, "[%pI6c]", &addr->ip6); 
     996+               else 
     997+                       return sprintf(buffer, "%pI6c", &addr->ip6); 
     998+       } 
     999+} 
     1000+#endif 
    9081001+ 
    9091002+/*** nat functions ***/ 
     
    9281021+static int 
    9291022+rtsp_mangle_tran(enum ip_conntrack_info ctinfo, 
    930 +                 struct nf_conntrack_expect* exp, 
    931 +                                                                struct ip_ct_rtsp_expect* prtspexp, 
    932 +                 struct sk_buff* skb, uint tranoff, uint tranlen) 
    933 +{ 
    934 +    char*       ptcp; 
    935 +    uint        tcplen; 
    936 +    char*       ptran; 
    937 +    char        rbuf1[16];      /* Replacement buffer (one port) */ 
    938 +    uint        rbuf1len;       /* Replacement len (one port) */ 
    939 +    char        rbufa[16];      /* Replacement buffer (all ports) */ 
    940 +    uint        rbufalen;       /* Replacement len (all ports) */ 
    941 +    u_int32_t   newip; 
    942 +    u_int16_t   loport, hiport; 
    943 +    uint        off = 0; 
    944 +    uint        diff;           /* Number of bytes we removed */ 
    945 + 
    946 +    struct nf_conn *ct = exp->master; 
    947 +    struct nf_conntrack_tuple *t; 
    948 + 
    949 +    char    szextaddr[15+1]; 
    950 +    uint    extaddrlen; 
    951 +    int     is_stun; 
    952 + 
    953 +    get_skb_tcpdata(skb, &ptcp, &tcplen); 
    954 +    ptran = ptcp+tranoff; 
    955 + 
    956 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || 
    957 +        tranlen < 10 || !iseol(ptran[tranlen-1]) || 
    958 +        nf_strncasecmp(ptran, "Transport:", 10) != 0) 
    959 +    { 
    960 +        pr_info("sanity check failed\n"); 
    961 +        return 0; 
    962 +    } 
    963 +    off += 10; 
    964 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off); 
    965 + 
    966 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; 
    967 +    t = &exp->tuple; 
    968 +    t->dst.u3.ip = newip; 
    969 + 
    970 +    extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) 
    971 +                       : sprintf(szextaddr, "%pI4", &newip); 
    972 +    pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); 
    973 + 
    974 +    rbuf1len = rbufalen = 0; 
    975 +    switch (prtspexp->pbtype) 
    976 +    { 
    977 +    case pb_single: 
    978 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ 
    979 +        { 
    980 +            t->dst.u.udp.port = htons(loport); 
    981 +            if (nf_ct_expect_related(exp) == 0) 
    982 +            { 
    983 +                pr_debug("using port %hu\n", loport); 
    984 +                break; 
    985 +            } 
    986 +        } 
    987 +        if (loport != 0) 
    988 +        { 
    989 +            rbuf1len = sprintf(rbuf1, "%hu", loport); 
    990 +            rbufalen = sprintf(rbufa, "%hu", loport); 
    991 +        } 
    992 +        break; 
    993 +    case pb_range: 
    994 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */ 
    995 +        { 
    996 +            t->dst.u.udp.port = htons(loport); 
    997 +            if (nf_ct_expect_related(exp) == 0) 
    998 +            { 
    999 +                hiport = loport + 1; //~exp->mask.dst.u.udp.port; 
    1000 +                pr_debug("using ports %hu-%hu\n", loport, hiport); 
    1001 +                break; 
    1002 +            } 
    1003 +        } 
    1004 +        if (loport != 0) 
    1005 +        { 
    1006 +            rbuf1len = sprintf(rbuf1, "%hu", loport); 
    1007 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1); 
    1008 +        } 
    1009 +        break; 
    1010 +    case pb_discon: 
    1011 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ 
    1012 +        { 
    1013 +            t->dst.u.udp.port = htons(loport); 
    1014 +            if (nf_ct_expect_related(exp) == 0) 
    1015 +            { 
    1016 +                pr_debug("using port %hu (1 of 2)\n", loport); 
    1017 +                break; 
    1018 +            } 
    1019 +        } 
    1020 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */ 
    1021 +        { 
    1022 +            t->dst.u.udp.port = htons(hiport); 
    1023 +            if (nf_ct_expect_related(exp) == 0) 
    1024 +            { 
    1025 +                pr_debug("using port %hu (2 of 2)\n", hiport); 
    1026 +                break; 
    1027 +            } 
    1028 +        } 
    1029 +        if (loport != 0 && hiport != 0) 
    1030 +        { 
    1031 +            rbuf1len = sprintf(rbuf1, "%hu", loport); 
    1032 +            if (hiport == loport+1) 
    1033 +            { 
    1034 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); 
    1035 +            } 
    1036 +            else 
    1037 +            { 
    1038 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport); 
    1039 +            } 
    1040 +        } 
    1041 +        break; 
    1042 +    } 
    1043 + 
    1044 +    if (rbuf1len == 0) 
    1045 +    { 
    1046 +        return 0;   /* cannot get replacement port(s) */ 
    1047 +    } 
    1048 + 
    1049 +    /* Transport: tran;field;field=val,tran;field;field=val,... */ 
    1050 +    while (off < tranlen) 
    1051 +    { 
    1052 +        uint        saveoff; 
    1053 +        const char* pparamend; 
    1054 +        uint        nextparamoff; 
    1055 + 
    1056 +        pparamend = memchr(ptran+off, ',', tranlen-off); 
    1057 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; 
    1058 +        nextparamoff = pparamend-ptcp; 
    1059 + 
    1060 +        /* 
    1061 +         * We pass over each param twice.  On the first pass, we look for a 
    1062 +         * destination= field.  It is handled by the security policy.  If it 
    1063 +         * is present, allowed, and equal to our external address, we assume 
    1064 +         * that STUN is being used and we leave the client_port= field alone. 
    1065 +         */ 
    1066 +        is_stun = 0; 
    1067 +        saveoff = off; 
    1068 +        while (off < nextparamoff) 
    1069 +        { 
    1070 +            const char* pfieldend; 
    1071 +            uint        nextfieldoff; 
    1072 + 
    1073 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off); 
    1074 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; 
    1075 + 
    1076 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) 
    1077 +            { 
    1078 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) 
    1079 +                { 
    1080 +                    is_stun = 1; 
    1081 +                } 
    1082 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) 
    1083 +                { 
    1084 +                    diff = nextfieldoff-off; 
    1085 +                    if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, 
    1086 +                                                         off, diff, NULL, 0)) 
    1087 +                    { 
    1088 +                        /* mangle failed, all we can do is bail */ 
    1089 +                       nf_ct_unexpect_related(exp); 
    1090 +                        return 0; 
    1091 +                    } 
    1092 +                    get_skb_tcpdata(skb, &ptcp, &tcplen); 
    1093 +                    ptran = ptcp+tranoff; 
    1094 +                    tranlen -= diff; 
    1095 +                    nextparamoff -= diff; 
    1096 +                    nextfieldoff -= diff; 
    1097 +                } 
    1098 +            } 
    1099 + 
    1100 +            off = nextfieldoff; 
    1101 +        } 
    1102 +        if (is_stun) 
    1103 +        { 
    1104 +            continue; 
    1105 +        } 
    1106 +        off = saveoff; 
    1107 +        while (off < nextparamoff) 
    1108 +        { 
    1109 +            const char* pfieldend; 
    1110 +            uint        nextfieldoff; 
    1111 + 
    1112 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off); 
    1113 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; 
    1114 + 
    1115 +            if (strncmp(ptran+off, "client_port=", 12) == 0) 
    1116 +            { 
    1117 +                u_int16_t   port; 
    1118 +                uint        numlen; 
    1119 +                uint        origoff; 
    1120 +                uint        origlen; 
    1121 +                char*       rbuf    = rbuf1; 
    1122 +                uint        rbuflen = rbuf1len; 
    1123 + 
    1124 +                off += 12; 
    1125 +                origoff = (ptran-ptcp)+off; 
    1126 +                origlen = 0; 
    1127 +                numlen = nf_strtou16(ptran+off, &port); 
    1128 +                off += numlen; 
    1129 +                origlen += numlen; 
    1130 +                if (port != prtspexp->loport) 
    1131 +                { 
    1132 +                    pr_debug("multiple ports found, port %hu ignored\n", port); 
    1133 +                } 
    1134 +                else 
    1135 +                { 
    1136 +                    if (ptran[off] == '-' || ptran[off] == '/') 
    1137 +                    { 
    1138 +                        off++; 
    1139 +                        origlen++; 
    1140 +                        numlen = nf_strtou16(ptran+off, &port); 
    1141 +                        off += numlen; 
    1142 +                        origlen += numlen; 
    1143 +                        rbuf = rbufa; 
    1144 +                        rbuflen = rbufalen; 
    1145 +                    } 
    1146 + 
    1147 +                    /* 
    1148 +                     * note we cannot just memcpy() if the sizes are the same. 
    1149 +                     * the mangle function does skb resizing, checks for a 
    1150 +                     * cloned skb, and updates the checksums. 
    1151 +                     * 
    1152 +                     * parameter 4 below is offset from start of tcp data. 
    1153 +                     */ 
    1154 +                    diff = origlen-rbuflen; 
    1155 +                    if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, 
    1156 +                                              origoff, origlen, rbuf, rbuflen)) 
    1157 +                    { 
    1158 +                        /* mangle failed, all we can do is bail */ 
    1159 +                       nf_ct_unexpect_related(exp); 
    1160 +                        return 0; 
    1161 +                    } 
    1162 +                    get_skb_tcpdata(skb, &ptcp, &tcplen); 
    1163 +                    ptran = ptcp+tranoff; 
    1164 +                    tranlen -= diff; 
    1165 +                    nextparamoff -= diff; 
    1166 +                    nextfieldoff -= diff; 
    1167 +                } 
    1168 +            } 
    1169 + 
    1170 +            off = nextfieldoff; 
    1171 +        } 
    1172 + 
    1173 +        off = nextparamoff; 
    1174 +    } 
    1175 + 
    1176 +    return 1; 
     1023+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1024+                unsigned int protoff, 
     1025+#endif 
     1026+                struct nf_conntrack_expect* rtp_exp, 
     1027+                struct nf_conntrack_expect* rtcp_exp, 
     1028+                struct ip_ct_rtsp_expect* prtspexp, 
     1029+                struct sk_buff* skb, uint tranoff, uint tranlen) 
     1030+{ 
     1031+       char*  ptcp; 
     1032+       uint   tcplen; 
     1033+       char*  ptran; 
     1034+       char   rbuf1[16];         /* Replacement buffer (one port) */ 
     1035+       uint   rbuf1len;          /* Replacement len (one port) */ 
     1036+       char   rbufa[16];         /* Replacement buffer (all ports) */ 
     1037+       uint   rbufalen;          /* Replacement len (all ports) */ 
     1038+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1039+       union nf_inet_addr newip; 
     1040+#else 
     1041+       u_int32_t  newip; 
     1042+#endif 
     1043+       u_int16_t loport, hiport; 
     1044+       uint      off = 0; 
     1045+       uint      diff;            /* Number of bytes we removed */ 
     1046+ 
     1047+       struct nf_conn *ct = rtp_exp->master; 
     1048+       /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */ 
     1049+       struct nf_conntrack_tuple *rtp_t; 
     1050+ 
     1051+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1052+       char szextaddr[INET6_ADDRSTRLEN]; 
     1053+#else 
     1054+       char szextaddr[INET_ADDRSTRLEN]; 
     1055+#endif 
     1056+       uint extaddrlen; 
     1057+       int  is_stun; 
     1058+ 
     1059+       get_skb_tcpdata(skb, &ptcp, &tcplen); 
     1060+       ptran = ptcp+tranoff; 
     1061+ 
     1062+       if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || 
     1063+           tranlen < 10 || !iseol(ptran[tranlen-1]) || 
     1064+           nf_strncasecmp(ptran, "Transport:", 10) != 0) { 
     1065+               pr_info("sanity check failed\n"); 
     1066+               return 0; 
     1067+       } 
     1068+       off += 10; 
     1069+       SKIP_WSPACE(ptcp+tranoff, tranlen, off); 
     1070+ 
     1071+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1072+       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3; 
     1073+       rtp_t = &rtp_exp->tuple; 
     1074+       rtp_t->dst.u3 = newip; 
     1075+       if (rtcp_exp) { 
     1076+               rtcp_exp->tuple.dst.u3 = newip; 
     1077+       } 
     1078+       extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip 
     1079+       pr_debug("stunaddr=%s (auto)\n", szextaddr); 
     1080+#else 
     1081+       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; 
     1082+       rtp_t = &rtp_exp->tuple; 
     1083+       rtp_t->dst.u3.ip = newip; 
     1084+       if (rtcp_exp) { 
     1085+               rtcp_exp->tuple.dst.u3.ip = newip; 
     1086+       } 
     1087+       extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) 
     1088+                          : sprintf(szextaddr, "%pI4", &newip); 
     1089+       pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); 
     1090+#endif 
     1091+       hiport = 0; 
     1092+       rbuf1len = rbufalen = 0; 
     1093+       switch (prtspexp->pbtype) { 
     1094+       case pb_single: 
     1095+               for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ 
     1096+                       rtp_t->dst.u.udp.port = htons(loport); 
     1097+                       if (nf_ct_expect_related(rtp_exp) == 0) { 
     1098+                               pr_debug("using port %hu\n", loport); 
     1099+                               break; 
     1100+                       } 
     1101+               } 
     1102+               if (loport != 0) { 
     1103+                       rbuf1len = sprintf(rbuf1, "%hu", loport); 
     1104+                       rbufalen = sprintf(rbufa, "%hu", loport); 
     1105+               } 
     1106+               break; 
     1107+       case pb_range: 
     1108+               for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */ 
     1109+                       rtp_t->dst.u.udp.port = htons(loport); 
     1110+                       if (nf_ct_expect_related(rtp_exp) != 0) { 
     1111+                               continue; 
     1112+                       } 
     1113+                       hiport = loport + 1; 
     1114+                       rtcp_exp->tuple.dst.u.udp.port = htons(hiport); 
     1115+                       if (nf_ct_expect_related(rtcp_exp) != 0) { 
     1116+                               nf_ct_unexpect_related(rtp_exp); 
     1117+                               continue; 
     1118+                       } 
     1119+ 
     1120+                       /* FIXME: invalid print in case of ipv6 */ 
     1121+                       pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n", 
     1122+                                &rtp_exp->tuple.src.u3.ip, 
     1123+                                ntohs(rtp_exp->tuple.src.u.udp.port), 
     1124+                                ntohs(rtcp_exp->tuple.src.u.udp.port), 
     1125+                                &rtp_exp->tuple.dst.u3.ip, 
     1126+                                ntohs(rtp_exp->tuple.dst.u.udp.port), 
     1127+                                ntohs(rtcp_exp->tuple.dst.u.udp.port)); 
     1128+                       break; 
     1129+               } 
     1130+               if (loport != 0) { 
     1131+                       rbuf1len = sprintf(rbuf1, "%hu", loport); 
     1132+                       rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); 
     1133+               } 
     1134+               break; 
     1135+       case pb_discon: 
     1136+               for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ 
     1137+                       rtp_t->dst.u.udp.port = htons(loport); 
     1138+                       if (nf_ct_expect_related(rtp_exp) == 0) { 
     1139+                               pr_debug("using port %hu (1 of 2)\n", loport); 
     1140+                               break; 
     1141+                       } 
     1142+               } 
     1143+               for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */ 
     1144+                       rtp_t->dst.u.udp.port = htons(hiport); 
     1145+                       if (nf_ct_expect_related(rtp_exp) == 0) { 
     1146+                               pr_debug("using port %hu (2 of 2)\n", hiport); 
     1147+                               break; 
     1148+                       } 
     1149+               } 
     1150+               if (loport != 0 && hiport != 0) { 
     1151+                       rbuf1len = sprintf(rbuf1, "%hu", loport); 
     1152+                       rbufalen = sprintf(rbufa, hiport == loport+1 ? 
     1153+                                          "%hu-%hu":"%hu/%hu", loport, hiport); 
     1154+               } 
     1155+               break; 
     1156+       } 
     1157+ 
     1158+       if (rbuf1len == 0) 
     1159+               return 0;   /* cannot get replacement port(s) */ 
     1160+ 
     1161+       /* Transport: tran;field;field=val,tran;field;field=val,... 
     1162+          `off` is set to the start of Transport value from start of line 
     1163+       */ 
     1164+       while (off < tranlen) { 
     1165+               uint        saveoff; 
     1166+               const char* pparamend; 
     1167+               uint        nextparamoff; 
     1168+ 
     1169+               pparamend = memchr(ptran+off, ',', tranlen-off); 
     1170+               pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; 
     1171+               nextparamoff = pparamend-ptran; 
     1172+ 
     1173+               /* 
     1174+                * We pass over each param twice.  On the first pass, we look for a 
     1175+                * destination= field.  It is handled by the security policy.  If it 
     1176+                * is present, allowed, and equal to our external address, we assume 
     1177+                * that STUN is being used and we leave the client_port= field alone. 
     1178+                */ 
     1179+               is_stun = 0; 
     1180+               saveoff = off; 
     1181+               while (off < nextparamoff) { 
     1182+                       const char* pfieldend; 
     1183+                       uint        nextfieldoff; 
     1184+ 
     1185+                       pfieldend = memchr(ptran+off, ';', nextparamoff-off); 
     1186+                       nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; 
     1187+ 
     1188+                       if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) { 
     1189+                               if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) 
     1190+                                       is_stun = 1; 
     1191+ 
     1192+                               if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { 
     1193+                                       uint dstoff = (ptran-ptcp)+off; 
     1194+                                       uint dstlen = nextfieldoff-off; 
     1195+                                       char* pdstrep = NULL; 
     1196+                                       uint dstreplen = 0; 
     1197+                                       diff = dstlen; 
     1198+                                       if (dstact == DSTACT_AUTO && !is_stun) { 
     1199+                                               pr_debug("RTSP: replace dst addr\n"); 
     1200+                                               dstoff += 12; 
     1201+                                               dstlen -= 13; 
     1202+                                               pdstrep = szextaddr; 
     1203+                                               dstreplen = extaddrlen; 
     1204+                                               diff = nextfieldoff-off-13-extaddrlen; 
     1205+                                       } 
     1206+ 
     1207+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1208+                                       if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, 
     1209+                                                                     dstoff, dstlen, pdstrep, dstreplen)) { 
     1210+#else 
     1211+                                       if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, 
     1212+                                                                     dstoff, dstlen, pdstrep, dstreplen)) { 
     1213+#endif 
     1214+                                               /* mangle failed, all we can do is bail */ 
     1215+                                               nf_ct_unexpect_related(rtp_exp); 
     1216+                                               if (rtcp_exp) 
     1217+                                                       nf_ct_unexpect_related(rtcp_exp); 
     1218+                                               return 0; 
     1219+                                       } 
     1220+                                       get_skb_tcpdata(skb, &ptcp, &tcplen); 
     1221+                                       ptran = ptcp+tranoff; 
     1222+                                       tranlen -= diff; 
     1223+                                       nextparamoff -= diff; 
     1224+                                       nextfieldoff -= diff; 
     1225+                               } 
     1226+                       } 
     1227+ 
     1228+                       off = nextfieldoff; 
     1229+               } 
     1230+ 
     1231+               if (is_stun) 
     1232+                       continue; 
     1233+ 
     1234+               off = saveoff; 
     1235+               while (off < nextparamoff) { 
     1236+                       const char* pfieldend; 
     1237+                       uint        nextfieldoff; 
     1238+ 
     1239+                       pfieldend = memchr(ptran+off, ';', nextparamoff-off); 
     1240+                       nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; 
     1241+ 
     1242+                       if (strncmp(ptran+off, "client_port=", 12) == 0) { 
     1243+                               u_int16_t port; 
     1244+                               uint      numlen; 
     1245+                               uint      origoff; 
     1246+                               uint      origlen; 
     1247+                               char*     rbuf = rbuf1; 
     1248+                               uint      rbuflen = rbuf1len; 
     1249+ 
     1250+                               off += 12; 
     1251+                               origoff = (ptran-ptcp)+off; 
     1252+                               origlen = 0; 
     1253+                               numlen = nf_strtou16(ptran+off, &port); 
     1254+                               off += numlen; 
     1255+                               origlen += numlen; 
     1256+                               if (port != prtspexp->loport) { 
     1257+                                       pr_debug("multiple ports found, port %hu ignored\n", port); 
     1258+                               } else { 
     1259+                                       if (ptran[off] == '-' || ptran[off] == '/') { 
     1260+                                               off++; 
     1261+                                               origlen++; 
     1262+                                               numlen = nf_strtou16(ptran+off, &port); 
     1263+                                               off += numlen; 
     1264+                                               origlen += numlen; 
     1265+                                               rbuf = rbufa; 
     1266+                                               rbuflen = rbufalen; 
     1267+                                       } 
     1268+ 
     1269+                                       /* 
     1270+                                        * note we cannot just memcpy() if the sizes are the same. 
     1271+                                        * the mangle function does skb resizing, checks for a 
     1272+                                        * cloned skb, and updates the checksums. 
     1273+                                        * 
     1274+                                        * parameter 4 below is offset from start of tcp data. 
     1275+                                        */ 
     1276+                                       diff = origlen-rbuflen; 
     1277+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1278+                                       if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, 
     1279+                                                                     origoff, origlen, rbuf, rbuflen)) { 
     1280+#else 
     1281+                                       if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, 
     1282+                                                                     origoff, origlen, rbuf, rbuflen)) { 
     1283+#endif 
     1284+                                               /* mangle failed, all we can do is bail */ 
     1285+                                               nf_ct_unexpect_related(rtp_exp); 
     1286+                                               if (rtcp_exp) 
     1287+                                                       nf_ct_unexpect_related(rtcp_exp); 
     1288+                                               return 0; 
     1289+                                       } 
     1290+                                       get_skb_tcpdata(skb, &ptcp, &tcplen); 
     1291+                                       ptran = ptcp+tranoff; 
     1292+                                       tranlen -= diff; 
     1293+                                       nextparamoff -= diff; 
     1294+                                       nextfieldoff -= diff; 
     1295+                               } 
     1296+                       } 
     1297+ 
     1298+                       off = nextfieldoff; 
     1299+               } 
     1300+ 
     1301+               off = nextparamoff; 
     1302+       } 
     1303+ 
     1304+       return 1; 
    11771305+} 
    11781306+ 
    11791307+static uint 
    11801308+help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, 
    1181 +        unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp,  
    1182 +        struct nf_conntrack_expect* exp) 
    1183 +{ 
    1184 +    char*   ptcp; 
    1185 +    uint    tcplen; 
    1186 +    uint    hdrsoff; 
    1187 +    uint    hdrslen; 
    1188 +    uint    lineoff; 
    1189 +    uint    linelen; 
    1190 +    uint    off; 
    1191 + 
    1192 +    //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; 
    1193 +    //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); 
    1194 + 
    1195 +    get_skb_tcpdata(skb, &ptcp, &tcplen); 
    1196 +    hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); 
    1197 +    hdrslen = matchlen; 
    1198 +    off = hdrsoff; 
    1199 +    pr_debug("NAT rtsp help_out\n"); 
    1200 + 
    1201 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) 
    1202 +    { 
    1203 +        if (linelen == 0) 
    1204 +        { 
    1205 +            break; 
    1206 +        } 
    1207 +        if (off > hdrsoff+hdrslen) 
    1208 +        { 
    1209 +            pr_info("!! overrun !!"); 
    1210 +            break; 
    1211 +        } 
    1212 +        pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); 
    1213 + 
    1214 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) 
    1215 +        { 
    1216 +            uint oldtcplen = tcplen; 
    1217 +           pr_debug("hdr: Transport\n"); 
    1218 +            if (!rtsp_mangle_tran(ctinfo, exp, prtspexp, skb, lineoff, linelen)) 
    1219 +            { 
    1220 +               pr_debug("hdr: Transport mangle failed"); 
    1221 +                break; 
    1222 +            } 
    1223 +            get_skb_tcpdata(skb, &ptcp, &tcplen); 
    1224 +            hdrslen -= (oldtcplen-tcplen); 
    1225 +            off -= (oldtcplen-tcplen); 
    1226 +            lineoff -= (oldtcplen-tcplen); 
    1227 +            linelen -= (oldtcplen-tcplen); 
    1228 +            pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); 
    1229 +        } 
    1230 +    } 
    1231 + 
    1232 +    return NF_ACCEPT; 
     1309+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1310+        unsigned int protoff, 
     1311+#endif 
     1312+        unsigned int matchoff, unsigned int matchlen, 
     1313+        struct ip_ct_rtsp_expect* prtspexp, 
     1314+        struct nf_conntrack_expect* rtp_exp, 
     1315+        struct nf_conntrack_expect* rtcp_exp) 
     1316+{ 
     1317+       char* ptcp; 
     1318+       uint  tcplen; 
     1319+       uint  hdrsoff; 
     1320+       uint  hdrslen; 
     1321+       uint  lineoff; 
     1322+       uint  linelen; 
     1323+       uint  off; 
     1324+       int   dir = CTINFO2DIR(ctinfo); 
     1325+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1326+       union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3; 
     1327+#else 
     1328+       __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip; 
     1329+#endif 
     1330+ 
     1331+       //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; 
     1332+       //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); 
     1333+ 
     1334+       get_skb_tcpdata(skb, &ptcp, &tcplen); 
     1335+       hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); 
     1336+       hdrslen = matchlen; 
     1337+       off = hdrsoff; 
     1338+       pr_debug("NAT rtsp help_out\n"); 
     1339+ 
     1340+       while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) { 
     1341+               if (linelen == 0) 
     1342+                       break; 
     1343+ 
     1344+               if (off > hdrsoff+hdrslen) { 
     1345+                       pr_info("!! overrun !!"); 
     1346+                       break; 
     1347+               } 
     1348+               pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); 
     1349+ 
     1350+               if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { 
     1351+                       uint oldtcplen = tcplen; 
     1352+                       pr_debug("hdr: Transport\n"); 
     1353+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1354+                       if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp, 
     1355+                                             prtspexp, skb, lineoff, linelen)) { 
     1356+#else 
     1357+                       if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp, 
     1358+                                             skb, lineoff, linelen)) { 
     1359+#endif 
     1360+                               pr_debug("hdr: Transport mangle failed"); 
     1361+                               break; 
     1362+                       } 
     1363+                       rtp_exp->expectfn = nf_nat_rtsp_expected; 
     1364+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1365+                       rtp_exp->saved_addr = saddr; 
     1366+#else 
     1367+                       rtp_exp->saved_ip = saddr; 
     1368+#endif 
     1369+                       rtp_exp->saved_proto.udp.port = htons(prtspexp->loport); 
     1370+                       rtp_exp->dir = !dir; 
     1371+                       if (rtcp_exp) { 
     1372+                               rtcp_exp->expectfn = nf_nat_rtsp_expected; 
     1373+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1374+                               rtcp_exp->saved_addr = saddr; 
     1375+#else 
     1376+                               rtcp_exp->saved_ip = saddr; 
     1377+#endif 
     1378+                               rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport); 
     1379+                               rtcp_exp->dir = !dir; 
     1380+                       } 
     1381+                       get_skb_tcpdata(skb, &ptcp, &tcplen); 
     1382+                       hdrslen -= (oldtcplen-tcplen); 
     1383+                       off -= (oldtcplen-tcplen); 
     1384+                       lineoff -= (oldtcplen-tcplen); 
     1385+                       linelen -= (oldtcplen-tcplen); 
     1386+                       pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); 
     1387+               } 
     1388+       } 
     1389+ 
     1390+       return NF_ACCEPT; 
    12331391+} 
    12341392+ 
    12351393+static unsigned int 
    1236 +help(struct sk_buff *skb, enum ip_conntrack_info ctinfo,  
    1237 +     unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp, 
    1238 +     struct nf_conntrack_expect* exp) 
    1239 +{ 
    1240 +    int dir = CTINFO2DIR(ctinfo); 
    1241 +    int rc = NF_ACCEPT; 
    1242 + 
    1243 +    switch (dir) 
    1244 +    { 
    1245 +    case IP_CT_DIR_ORIGINAL: 
    1246 +        rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, exp); 
    1247 +        break; 
    1248 +    case IP_CT_DIR_REPLY: 
    1249 +       pr_debug("unmangle ! %u\n", ctinfo); 
    1250 +       /* XXX: unmangle */ 
    1251 +       rc = NF_ACCEPT; 
    1252 +        break; 
    1253 +    } 
    1254 +    //UNLOCK_BH(&ip_rtsp_lock); 
    1255 + 
    1256 +    return rc; 
    1257 +} 
    1258 + 
    1259 +static void expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) 
    1260 +{ 
    1261 +    struct nf_nat_ipv4_multi_range_compat mr; 
    1262 +    u_int32_t newdstip, newsrcip, newip; 
    1263 + 
    1264 +    struct nf_conn *master = ct->master; 
    1265 + 
    1266 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; 
    1267 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; 
    1268 +    //FIXME (how to port that ?) 
    1269 +    //code from 2.4 : newip = (HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC) ? newsrcip : newdstip; 
    1270 +    newip = newdstip; 
    1271 + 
    1272 +    pr_debug("newsrcip=%pI4, newdstip=%pI4, newip=%pI4\n", 
    1273 +           &newsrcip, &newdstip, &newip); 
    1274 + 
    1275 +    mr.rangesize = 1; 
    1276 +    // We don't want to manip the per-protocol, just the IPs.  
    1277 +    mr.range[0].flags = NF_NAT_RANGE_MAP_IPS; 
    1278 +    mr.range[0].min_ip = mr.range[0].max_ip = newip; 
    1279 + 
    1280 +    nf_nat_setup_info(ct, &mr.range[0], NF_NAT_MANIP_DST); 
     1394+nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo, 
     1395+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1396+           unsigned int protoff, 
     1397+#endif 
     1398+           unsigned int matchoff, unsigned int matchlen, 
     1399+           struct ip_ct_rtsp_expect* prtspexp, 
     1400+           struct nf_conntrack_expect* rtp_exp, 
     1401+           struct nf_conntrack_expect* rtcp_exp) 
     1402+{ 
     1403+       int dir = CTINFO2DIR(ctinfo); 
     1404+       int rc = NF_ACCEPT; 
     1405+ 
     1406+       switch (dir) { 
     1407+       case IP_CT_DIR_ORIGINAL: 
     1408+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1409+               rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, 
     1410+                             rtp_exp, rtcp_exp); 
     1411+#else 
     1412+               rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, 
     1413+                             rtp_exp, rtcp_exp); 
     1414+#endif 
     1415+               break; 
     1416+       case IP_CT_DIR_REPLY: 
     1417+               pr_debug("unmangle ! %u\n", ctinfo); 
     1418+               /* XXX: unmangle */ 
     1419+               rc = NF_ACCEPT; 
     1420+               break; 
     1421+       } 
     1422+       //UNLOCK_BH(&ip_rtsp_lock); 
     1423+ 
     1424+       return rc; 
     1425+} 
     1426+ 
     1427+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) 
     1428+{ 
     1429+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1430+       struct nf_nat_range range; 
     1431+#else 
     1432+       struct nf_nat_ipv4_range range; 
     1433+#endif 
     1434+ 
     1435+       /* This must be a fresh one. */ 
     1436+       BUG_ON(ct->status & IPS_NAT_DONE_MASK); 
     1437+ 
     1438+       /* For DST manip, map port here to where it's expected. */ 
     1439+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1440+       range.min_proto = range.max_proto = exp->saved_proto; 
     1441+       range.min_addr = range.max_addr = exp->saved_addr; 
     1442+#else 
     1443+       range.min = range.max = exp->saved_proto; 
     1444+       range.min_ip = range.max_ip = exp->saved_ip; 
     1445+#endif 
     1446+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) 
     1447+       range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); 
     1448+       nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); 
     1449+#else 
     1450+       range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); 
     1451+       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); 
     1452+#endif 
     1453+ 
     1454+       /* Change src to where master sends to, but only if the connection 
     1455+        * actually came from the same source. */ 
     1456+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 
     1457+       if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, 
     1458+                            &ct->master->tuplehash[exp->dir].tuple.src.u3)) { 
     1459+               range.min_addr = range.max_addr 
     1460+                       = ct->master->tuplehash[!exp->dir].tuple.dst.u3; 
     1461+#else 
     1462+       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 
     1463+           ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { 
     1464+               range.min_ip = range.max_ip 
     1465+                       = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; 
     1466+#endif 
     1467+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) 
     1468+               range.flags = NF_NAT_RANGE_MAP_IPS; 
     1469+               nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); 
     1470+#else 
     1471+               range.flags = IP_NAT_RANGE_MAP_IPS; 
     1472+               nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); 
     1473+#endif 
     1474+       } 
    12811475+} 
    12821476+ 
     
    12841478+static void __exit fini(void) 
    12851479+{ 
    1286 +       nf_nat_rtsp_hook = NULL; 
    1287 +        nf_nat_rtsp_hook_expectfn = NULL; 
     1480+       rcu_assign_pointer(nf_nat_rtsp_hook, NULL); 
    12881481+       synchronize_net(); 
    12891482+} 
     
    12941487+ 
    12951488+       BUG_ON(nf_nat_rtsp_hook); 
    1296 +       nf_nat_rtsp_hook = help; 
    1297 +        nf_nat_rtsp_hook_expectfn = &expected; 
     1489+       rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp); 
    12981490+ 
    12991491+       if (stunaddr != NULL) 
     
    13011493+ 
    13021494+       if (destaction != NULL) { 
    1303 +               if (strcmp(destaction, "auto") == 0) 
     1495+               if (strcmp(destaction, "auto") == 0) 
    13041496+                       dstact = DSTACT_AUTO; 
    13051497+ 
Note: See TracChangeset for help on using the changeset viewer.