source: branches/whiterussian/openwrt/target/linux/linux-2.4/patches/generic/117-netfilter_nat_rtsp.patch @ 3290

Last change on this file since 3290 was 3290, checked in by florian, 10 years ago

Remove SIP connection tracking helpers, licence unclear, too many unresolved symbols

File size: 46.3 KB
  • net/ipv4/netfilter/Config.in

    diff -urN linux-2.4.30/net/ipv4/netfilter/Config.in linux-2.4.30.new/net/ipv4/netfilter/Config.in
    old new  
    1414  dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK 
    1515  dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE 
    1616  dep_tristate '  H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK 
     17  dep_tristate '  RTSP protocol support' CONFIG_IP_NF_RTSP $CONFIG_IP_NF_CONNTRACK 
    1718fi 
    1819 
    1920if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 
     
    102103         define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT 
    103104       fi 
    104105      fi 
     106      if [ "$CONFIG_IP_NF_RTSP" = "m" ]; then 
     107        define_tristate CONFIG_IP_NF_NAT_RTSP m 
     108      else 
     109       if [ "$CONFIG_IP_NF_RTSP" = "y" ]; then 
     110         define_tristate CONFIG_IP_NF_NAT_RTSP $CONFIG_IP_NF_NAT 
     111       fi 
     112      fi 
    105113      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 
    106114        dep_tristate '    Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT 
    107115      fi 
  • net/ipv4/netfilter/Makefile

    diff -urN linux-2.4.30/net/ipv4/netfilter/Makefile linux-2.4.30.new/net/ipv4/netfilter/Makefile
    old new  
    5757ifdef CONFIG_IP_NF_NAT_H323 
    5858       export-objs += ip_conntrack_h323.o 
    5959endif 
     60obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o 
     61ifdef CONFIG_IP_NF_NAT_RTSP 
     62       export-objs += ip_conntrack_rtsp.o 
     63endif 
     64 
    6065 
    6166 
    6267# NAT helpers  
     
    6772obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o 
    6873obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o 
    6974obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o 
     75obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o 
    7076 
    7177# generic IP tables  
    7278obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o 
  • net/ipv4/netfilter/ip_conntrack_rtsp.c

    diff -urN linux-2.4.30/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.4.30.new/net/ipv4/netfilter/ip_conntrack_rtsp.c
    old new  
     1/* 
     2 * RTSP extension for IP connection tracking 
     3 * (C) 2003 by Tom Marshall <tmarshall@real.com> 
     4 * based on ip_conntrack_irc.c 
     5 * 
     6 *      This program is free software; you can redistribute it and/or 
     7 *      modify it under the terms of the GNU General Public License 
     8 *      as published by the Free Software Foundation; either version 
     9 *      2 of the License, or (at your option) any later version. 
     10 * 
     11 * Module load syntax: 
     12 *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS> 
     13 *                              max_outstanding=n setup_timeout=secs 
     14 * 
     15 * If no ports are specified, the default will be port 554. 
     16 * 
     17 * With max_outstanding you can define the maximum number of not yet 
     18 * answered SETUP requests per RTSP session (default 8). 
     19 * With setup_timeout you can specify how long the system waits for 
     20 * an expected data channel (default 300 seconds). 
     21 */ 
     22 
     23#include <linux/config.h> 
     24#include <linux/module.h> 
     25#include <linux/netfilter.h> 
     26#include <linux/ip.h> 
     27#include <net/checksum.h> 
     28#include <net/tcp.h> 
     29 
     30#include <linux/netfilter_ipv4/lockhelp.h> 
     31#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 
     32#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h> 
     33 
     34#include <linux/ctype.h> 
     35#define NF_NEED_STRNCASECMP 
     36#define NF_NEED_STRTOU16 
     37#define NF_NEED_STRTOU32 
     38#define NF_NEED_NEXTLINE 
     39#include <linux/netfilter_helpers.h> 
     40#define NF_NEED_MIME_NEXTLINE 
     41#include <linux/netfilter_mime.h> 
     42 
     43#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */ 
     44 
     45#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) 
     46#ifdef IP_NF_RTSP_DEBUG 
     47#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) 
     48#else 
     49#define DEBUGP(fmt, args...) 
     50#endif 
     51 
     52#define MAX_PORTS 8 
     53static int ports[MAX_PORTS]; 
     54static int num_ports = 0; 
     55static int max_outstanding = 8; 
     56static unsigned int setup_timeout = 300; 
     57 
     58MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>"); 
     59MODULE_DESCRIPTION("RTSP connection tracking module"); 
     60MODULE_LICENSE("GPL"); 
     61#ifdef MODULE_PARM 
     62MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); 
     63MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); 
     64MODULE_PARM(max_outstanding, "i"); 
     65MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); 
     66MODULE_PARM(setup_timeout, "i"); 
     67MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); 
     68#endif 
     69 
     70DECLARE_LOCK(ip_rtsp_lock); 
     71struct module* ip_conntrack_rtsp = THIS_MODULE; 
     72 
     73/* 
     74 * Max mappings we will allow for one RTSP connection (for RTP, the number 
     75 * of allocated ports is twice this value).  Note that SMIL burns a lot of 
     76 * ports so keep this reasonably high.  If this is too low, you will see a 
     77 * lot of "no free client map entries" messages. 
     78 */ 
     79#define MAX_PORT_MAPS 16 
     80 
     81/*** default port list was here in the masq code: 554, 3030, 4040 ***/ 
     82 
     83#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } 
     84 
     85/* 
     86 * Parse an RTSP packet. 
     87 * 
     88 * Returns zero if parsing failed. 
     89 * 
     90 * Parameters: 
     91 *  IN      ptcp        tcp data pointer 
     92 *  IN      tcplen      tcp data len 
     93 *  IN/OUT  ptcpoff     points to current tcp offset 
     94 *  OUT     phdrsoff    set to offset of rtsp headers 
     95 *  OUT     phdrslen    set to length of rtsp headers 
     96 *  OUT     pcseqoff    set to offset of CSeq header 
     97 *  OUT     pcseqlen    set to length of CSeq header 
     98 */ 
     99static int 
     100rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, 
     101                   uint* phdrsoff, uint* phdrslen, 
     102                   uint* pcseqoff, uint* pcseqlen) 
     103{ 
     104    uint    entitylen = 0; 
     105    uint    lineoff; 
     106    uint    linelen; 
     107 
     108    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) 
     109    { 
     110        return 0; 
     111    } 
     112 
     113    *phdrsoff = *ptcpoff; 
     114    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) 
     115    { 
     116        if (linelen == 0) 
     117        { 
     118            if (entitylen > 0) 
     119            { 
     120                *ptcpoff += min(entitylen, tcplen - *ptcpoff); 
     121            } 
     122            break; 
     123        } 
     124        if (lineoff+linelen > tcplen) 
     125        { 
     126            INFOP("!! overrun !!\n"); 
     127            break; 
     128        } 
     129 
     130        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) 
     131        { 
     132            *pcseqoff = lineoff; 
     133            *pcseqlen = linelen; 
     134        } 
     135        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) 
     136        { 
     137            uint off = lineoff+15; 
     138            SKIP_WSPACE(ptcp+lineoff, linelen, off); 
     139            nf_strtou32(ptcp+off, &entitylen); 
     140        } 
     141    } 
     142    *phdrslen = (*ptcpoff) - (*phdrsoff); 
     143 
     144    return 1; 
     145} 
     146 
     147/* 
     148 * Find lo/hi client ports (if any) in transport header 
     149 * In: 
     150 *   ptcp, tcplen = packet 
     151 *   tranoff, tranlen = buffer to search 
     152 * 
     153 * Out: 
     154 *   pport_lo, pport_hi = lo/hi ports (host endian) 
     155 * 
     156 * Returns nonzero if any client ports found 
     157 * 
     158 * Note: it is valid (and expected) for the client to request multiple 
     159 * transports, so we need to parse the entire line. 
     160 */ 
     161static int 
     162rtsp_parse_transport(char* ptran, uint tranlen, 
     163                     struct ip_ct_rtsp_expect* prtspexp) 
     164{ 
     165    int     rc = 0; 
     166    uint    off = 0; 
     167 
     168    if (tranlen < 10 || !iseol(ptran[tranlen-1]) || 
     169        nf_strncasecmp(ptran, "Transport:", 10) != 0) 
     170    { 
     171        INFOP("sanity check failed\n"); 
     172        return 0; 
     173    } 
     174    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran); 
     175    off += 10; 
     176    SKIP_WSPACE(ptran, tranlen, off); 
     177 
     178    /* Transport: tran;field;field=val,tran;field;field=val,... */ 
     179    while (off < tranlen) 
     180    { 
     181        const char* pparamend; 
     182        uint        nextparamoff; 
     183 
     184        pparamend = memchr(ptran+off, ',', tranlen-off); 
     185        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; 
     186        nextparamoff = pparamend-ptran; 
     187 
     188        while (off < nextparamoff) 
     189        { 
     190            const char* pfieldend; 
     191            uint        nextfieldoff; 
     192 
     193            pfieldend = memchr(ptran+off, ';', nextparamoff-off); 
     194            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; 
     195 
     196            if (strncmp(ptran+off, "client_port=", 12) == 0) 
     197            { 
     198                u_int16_t   port; 
     199                uint        numlen; 
     200 
     201                off += 12; 
     202                numlen = nf_strtou16(ptran+off, &port); 
     203                off += numlen; 
     204                if (prtspexp->loport != 0 && prtspexp->loport != port) 
     205                { 
     206                    DEBUGP("multiple ports found, port %hu ignored\n", port); 
     207                } 
     208                else 
     209                { 
     210                    prtspexp->loport = prtspexp->hiport = port; 
     211                    if (ptran[off] == '-') 
     212                    { 
     213                        off++; 
     214                        numlen = nf_strtou16(ptran+off, &port); 
     215                        off += numlen; 
     216                        prtspexp->pbtype = pb_range; 
     217                        prtspexp->hiport = port; 
     218 
     219                        // If we have a range, assume rtp: 
     220                        // loport must be even, hiport must be loport+1 
     221                        if ((prtspexp->loport & 0x0001) != 0 || 
     222                            prtspexp->hiport != prtspexp->loport+1) 
     223                        { 
     224                            DEBUGP("incorrect range: %hu-%hu, correcting\n", 
     225                                   prtspexp->loport, prtspexp->hiport); 
     226                            prtspexp->loport &= 0xfffe; 
     227                            prtspexp->hiport = prtspexp->loport+1; 
     228                        } 
     229                    } 
     230                    else if (ptran[off] == '/') 
     231                    { 
     232                        off++; 
     233                        numlen = nf_strtou16(ptran+off, &port); 
     234                        off += numlen; 
     235                        prtspexp->pbtype = pb_discon; 
     236                        prtspexp->hiport = port; 
     237                    } 
     238                    rc = 1; 
     239                } 
     240            } 
     241 
     242            /* 
     243             * Note we don't look for the destination parameter here. 
     244             * If we are using NAT, the NAT module will handle it.  If not, 
     245             * and the client is sending packets elsewhere, the expectation 
     246             * will quietly time out. 
     247             */ 
     248 
     249            off = nextfieldoff; 
     250        } 
     251 
     252        off = nextparamoff; 
     253    } 
     254 
     255    return rc; 
     256} 
     257 
     258/*** conntrack functions ***/ 
     259 
     260/* outbound packet: client->server */ 
     261static int 
     262help_out(const struct iphdr* iph, size_t pktlen, 
     263                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo) 
     264{ 
     265    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */ 
     266    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4; 
     267    uint    tcplen = pktlen - iph->ihl * 4; 
     268    char*   pdata = (char*)tcph + tcph->doff * 4; 
     269    uint    datalen = tcplen - tcph->doff * 4; 
     270    uint    dataoff = 0; 
     271 
     272    struct ip_conntrack_expect exp; 
     273 
     274    while (dataoff < datalen) 
     275    { 
     276        uint    cmdoff = dataoff; 
     277        uint    hdrsoff = 0; 
     278        uint    hdrslen = 0; 
     279        uint    cseqoff = 0; 
     280        uint    cseqlen = 0; 
     281        uint    lineoff = 0; 
     282        uint    linelen = 0; 
     283        uint    off; 
     284        int     rc; 
     285 
     286        if (!rtsp_parse_message(pdata, datalen, &dataoff, 
     287                                &hdrsoff, &hdrslen, 
     288                                &cseqoff, &cseqlen)) 
     289        { 
     290            break;      /* not a valid message */ 
     291        } 
     292 
     293        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) 
     294        { 
     295            continue;   /* not a SETUP message */ 
     296        } 
     297        DEBUGP("found a setup message\n"); 
     298 
     299        memset(&exp, 0, sizeof(exp)); 
     300 
     301        off = 0; 
     302        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off, 
     303                                &lineoff, &linelen)) 
     304        { 
     305            if (linelen == 0) 
     306            { 
     307                break; 
     308            } 
     309            if (off > hdrsoff+hdrslen) 
     310            { 
     311                INFOP("!! overrun !!"); 
     312                break; 
     313            } 
     314 
     315            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0) 
     316            { 
     317                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen, 
     318                                     &exp.help.exp_rtsp_info); 
     319            } 
     320        } 
     321 
     322        if (exp.help.exp_rtsp_info.loport == 0) 
     323        { 
     324            DEBUGP("no udp transports found\n"); 
     325            continue;   /* no udp transports found */ 
     326        } 
     327 
     328        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n", 
     329              (int)exp.help.exp_rtsp_info.pbtype, 
     330              exp.help.exp_rtsp_info.loport, 
     331              exp.help.exp_rtsp_info.hiport); 
     332 
     333        LOCK_BH(&ip_rtsp_lock); 
     334        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */ 
     335        exp.help.exp_rtsp_info.len = hdrslen; 
     336 
     337        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; 
     338        exp.mask.src.ip  = 0xffffffff; 
     339        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip; 
     340        exp.mask.dst.ip  = 0xffffffff; 
     341        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport; 
     342        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff; 
     343        exp.tuple.dst.protonum = IPPROTO_UDP; 
     344        exp.mask.dst.protonum  = 0xffff; 
     345 
     346        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n", 
     347                NIPQUAD(exp.tuple.src.ip), 
     348                ntohs(exp.tuple.src.u.tcp.port), 
     349                NIPQUAD(exp.tuple.dst.ip), 
     350                ntohs(exp.tuple.dst.u.tcp.port)); 
     351 
     352        /* pass the request off to the nat helper */ 
     353        rc = ip_conntrack_expect_related(ct, &exp); 
     354        UNLOCK_BH(&ip_rtsp_lock); 
     355        if (rc == 0) 
     356        { 
     357            DEBUGP("ip_conntrack_expect_related succeeded\n"); 
     358        } 
     359        else 
     360        { 
     361            INFOP("ip_conntrack_expect_related failed (%d)\n", rc); 
     362        } 
     363    } 
     364 
     365    return NF_ACCEPT; 
     366} 
     367 
     368/* inbound packet: server->client */ 
     369static int 
     370help_in(const struct iphdr* iph, size_t pktlen, 
     371                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo) 
     372{ 
     373    return NF_ACCEPT; 
     374} 
     375 
     376static int 
     377help(const struct iphdr* iph, size_t pktlen, 
     378                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo) 
     379{ 
     380    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */ 
     381    struct tcphdr* tcph = (void*)iph + iph->ihl * 4; 
     382    u_int32_t tcplen = pktlen - iph->ihl * 4; 
     383 
     384    /* Until there's been traffic both ways, don't look in packets. */ 
     385    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) 
     386    { 
     387        DEBUGP("conntrackinfo = %u\n", ctinfo); 
     388        return NF_ACCEPT; 
     389    } 
     390 
     391    /* Not whole TCP header? */ 
     392    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) 
     393    { 
     394        DEBUGP("tcplen = %u\n", (unsigned)tcplen); 
     395        return NF_ACCEPT; 
     396    } 
     397 
     398    /* Checksum invalid?  Ignore. */ 
     399    /* FIXME: Source route IP option packets --RR */ 
     400    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, 
     401                     csum_partial((char*)tcph, tcplen, 0))) 
     402    { 
     403        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", 
     404               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); 
     405        return NF_ACCEPT; 
     406    } 
     407 
     408    switch (CTINFO2DIR(ctinfo)) 
     409    { 
     410    case IP_CT_DIR_ORIGINAL: 
     411        help_out(iph, pktlen, ct, ctinfo); 
     412        break; 
     413    case IP_CT_DIR_REPLY: 
     414        help_in(iph, pktlen, ct, ctinfo); 
     415        break; 
     416    } 
     417 
     418    return NF_ACCEPT; 
     419} 
     420 
     421static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS]; 
     422static char rtsp_names[MAX_PORTS][10]; 
     423 
     424/* This function is intentionally _NOT_ defined as __exit */ 
     425static void 
     426fini(void) 
     427{ 
     428    int i; 
     429    for (i = 0; i < num_ports; i++) 
     430    { 
     431        DEBUGP("unregistering port %d\n", ports[i]); 
     432        ip_conntrack_helper_unregister(&rtsp_helpers[i]); 
     433    } 
     434} 
     435 
     436static int __init 
     437init(void) 
     438{ 
     439    int i, ret; 
     440    struct ip_conntrack_helper *hlpr; 
     441    char *tmpname; 
     442 
     443    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); 
     444 
     445    if (max_outstanding < 1) 
     446    { 
     447        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n"); 
     448        return -EBUSY; 
     449    } 
     450    if (setup_timeout < 0) 
     451    { 
     452        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n"); 
     453        return -EBUSY; 
     454    } 
     455 
     456    /* If no port given, default to standard rtsp port */ 
     457    if (ports[0] == 0) 
     458    { 
     459        ports[0] = RTSP_PORT; 
     460    } 
     461 
     462    for (i = 0; (i < MAX_PORTS) && ports[i]; i++) 
     463    { 
     464        hlpr = &rtsp_helpers[i]; 
     465        memset(hlpr, 0, sizeof(struct ip_conntrack_helper)); 
     466        hlpr->tuple.src.u.tcp.port = htons(ports[i]); 
     467        hlpr->tuple.dst.protonum = IPPROTO_TCP; 
     468        hlpr->mask.src.u.tcp.port = 0xFFFF; 
     469        hlpr->mask.dst.protonum = 0xFFFF; 
     470        hlpr->max_expected = max_outstanding; 
     471        hlpr->timeout = setup_timeout; 
     472        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT; 
     473        hlpr->me = ip_conntrack_rtsp; 
     474        hlpr->help = help; 
     475 
     476        tmpname = &rtsp_names[i][0]; 
     477        if (ports[i] == RTSP_PORT) 
     478        { 
     479            sprintf(tmpname, "rtsp"); 
     480        } 
     481        else 
     482        { 
     483            sprintf(tmpname, "rtsp-%d", i); 
     484        } 
     485        hlpr->name = tmpname; 
     486 
     487        DEBUGP("port #%d: %d\n", i, ports[i]); 
     488 
     489        ret = ip_conntrack_helper_register(hlpr); 
     490 
     491        if (ret) 
     492        { 
     493            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]); 
     494            fini(); 
     495            return -EBUSY; 
     496        } 
     497        num_ports++; 
     498    } 
     499    return 0; 
     500} 
     501 
     502#ifdef CONFIG_IP_NF_NAT_NEEDED 
     503EXPORT_SYMBOL(ip_rtsp_lock); 
     504#endif 
     505 
     506module_init(init); 
     507module_exit(fini); 
  • net/ipv4/netfilter/ip_nat_rtsp.c

    diff -urN linux-2.4.30/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.4.30.new/net/ipv4/netfilter/ip_nat_rtsp.c
    old new  
     1/* 
     2 * RTSP extension for TCP NAT alteration 
     3 * (C) 2003 by Tom Marshall <tmarshall@real.com> 
     4 * based on ip_nat_irc.c 
     5 * 
     6 *      This program is free software; you can redistribute it and/or 
     7 *      modify it under the terms of the GNU General Public License 
     8 *      as published by the Free Software Foundation; either version 
     9 *      2 of the License, or (at your option) any later version. 
     10 * 
     11 * Module load syntax: 
     12 *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS> 
     13 *                           stunaddr=<address> 
     14 *                           destaction=[auto|strip|none] 
     15 * 
     16 * If no ports are specified, the default will be port 554 only. 
     17 * 
     18 * stunaddr specifies the address used to detect that a client is using STUN. 
     19 * If this address is seen in the destination parameter, it is assumed that 
     20 * the client has already punched a UDP hole in the firewall, so we don't 
     21 * mangle the client_port.  If none is specified, it is autodetected.  It 
     22 * only needs to be set if you have multiple levels of NAT.  It should be 
     23 * set to the external address that the STUN clients detect.  Note that in 
     24 * this case, it will not be possible for clients to use UDP with servers 
     25 * between the NATs. 
     26 * 
     27 * If no destaction is specified, auto is used. 
     28 *   destaction=auto:  strip destination parameter if it is not stunaddr. 
     29 *   destaction=strip: always strip destination parameter (not recommended). 
     30 *   destaction=none:  do not touch destination parameter (not recommended). 
     31 */ 
     32 
     33#include <linux/module.h> 
     34#include <linux/netfilter_ipv4.h> 
     35#include <linux/ip.h> 
     36#include <linux/tcp.h> 
     37#include <linux/kernel.h> 
     38#include <net/tcp.h> 
     39#include <linux/netfilter_ipv4/ip_nat.h> 
     40#include <linux/netfilter_ipv4/ip_nat_helper.h> 
     41#include <linux/netfilter_ipv4/ip_nat_rule.h> 
     42#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h> 
     43#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 
     44 
     45#include <linux/inet.h> 
     46#include <linux/ctype.h> 
     47#define NF_NEED_STRNCASECMP 
     48#define NF_NEED_STRTOU16 
     49#include <linux/netfilter_helpers.h> 
     50#define NF_NEED_MIME_NEXTLINE 
     51#include <linux/netfilter_mime.h> 
     52 
     53#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) 
     54#ifdef IP_NF_RTSP_DEBUG 
     55#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) 
     56#else 
     57#define DEBUGP(fmt, args...) 
     58#endif 
     59 
     60#define MAX_PORTS       8 
     61#define DSTACT_AUTO     0 
     62#define DSTACT_STRIP    1 
     63#define DSTACT_NONE     2 
     64 
     65static int      ports[MAX_PORTS]; 
     66static char*    stunaddr = NULL; 
     67static char*    destaction = NULL; 
     68 
     69static int       num_ports = 0; 
     70static u_int32_t extip = 0; 
     71static int       dstact = 0; 
     72 
     73MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>"); 
     74MODULE_DESCRIPTION("RTSP network address translation module"); 
     75MODULE_LICENSE("GPL"); 
     76#ifdef MODULE_PARM 
     77MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); 
     78MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); 
     79MODULE_PARM(stunaddr, "s"); 
     80MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); 
     81MODULE_PARM(destaction, "s"); 
     82MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); 
     83#endif 
     84 
     85/* protects rtsp part of conntracks */ 
     86DECLARE_LOCK_EXTERN(ip_rtsp_lock); 
     87 
     88#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } 
     89 
     90/*** helper functions ***/ 
     91 
     92static void 
     93get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) 
     94{ 
     95    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph; 
     96    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4); 
     97 
     98    *pptcpdata = (char*)tcph + tcph->doff*4; 
     99    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata; 
     100} 
     101 
     102/*** nat functions ***/ 
     103 
     104/* 
     105 * Mangle the "Transport:" header: 
     106 *   - Replace all occurences of "client_port=<spec>" 
     107 *   - Handle destination parameter 
     108 * 
     109 * In: 
     110 *   ct, ctinfo = conntrack context 
     111 *   pskb       = packet 
     112 *   tranoff    = Transport header offset from TCP data 
     113 *   tranlen    = Transport header length (incl. CRLF) 
     114 *   rport_lo   = replacement low  port (host endian) 
     115 *   rport_hi   = replacement high port (host endian) 
     116 * 
     117 * Returns packet size difference. 
     118 * 
     119 * Assumes that a complete transport header is present, ending with CR or LF 
     120 */ 
     121static int 
     122rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo, 
     123                 struct ip_conntrack_expect* exp, 
     124                 struct sk_buff** pskb, uint tranoff, uint tranlen) 
     125{ 
     126    char*       ptcp; 
     127    uint        tcplen; 
     128    char*       ptran; 
     129    char        rbuf1[16];      /* Replacement buffer (one port) */ 
     130    uint        rbuf1len;       /* Replacement len (one port) */ 
     131    char        rbufa[16];      /* Replacement buffer (all ports) */ 
     132    uint        rbufalen;       /* Replacement len (all ports) */ 
     133    u_int32_t   newip; 
     134    u_int16_t   loport, hiport; 
     135    uint        off = 0; 
     136    uint        diff;           /* Number of bytes we removed */ 
     137 
     138    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info; 
     139    struct ip_conntrack_tuple t; 
     140 
     141    char    szextaddr[15+1]; 
     142    uint    extaddrlen; 
     143    int     is_stun; 
     144 
     145    get_skb_tcpdata(*pskb, &ptcp, &tcplen); 
     146    ptran = ptcp+tranoff; 
     147 
     148    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || 
     149        tranlen < 10 || !iseol(ptran[tranlen-1]) || 
     150        nf_strncasecmp(ptran, "Transport:", 10) != 0) 
     151    { 
     152        INFOP("sanity check failed\n"); 
     153        return 0; 
     154    } 
     155    off += 10; 
     156    SKIP_WSPACE(ptcp+tranoff, tranlen, off); 
     157 
     158    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; 
     159    t = exp->tuple; 
     160    t.dst.ip = newip; 
     161 
     162    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip)) 
     163                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip)); 
     164    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); 
     165 
     166    rbuf1len = rbufalen = 0; 
     167    switch (prtspexp->pbtype) 
     168    { 
     169    case pb_single: 
     170        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ 
     171        { 
     172            t.dst.u.udp.port = htons(loport); 
     173            if (ip_conntrack_change_expect(exp, &t) == 0) 
     174            { 
     175                DEBUGP("using port %hu\n", loport); 
     176                break; 
     177            } 
     178        } 
     179        if (loport != 0) 
     180        { 
     181            rbuf1len = sprintf(rbuf1, "%hu", loport); 
     182            rbufalen = sprintf(rbufa, "%hu", loport); 
     183        } 
     184        break; 
     185    case pb_range: 
     186        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */ 
     187        { 
     188            t.dst.u.udp.port = htons(loport); 
     189            if (ip_conntrack_change_expect(exp, &t) == 0) 
     190            { 
     191                hiport = loport + ~exp->mask.dst.u.udp.port; 
     192                DEBUGP("using ports %hu-%hu\n", loport, hiport); 
     193                break; 
     194            } 
     195        } 
     196        if (loport != 0) 
     197        { 
     198            rbuf1len = sprintf(rbuf1, "%hu", loport); 
     199            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1); 
     200        } 
     201        break; 
     202    case pb_discon: 
     203        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ 
     204        { 
     205            t.dst.u.udp.port = htons(loport); 
     206            if (ip_conntrack_change_expect(exp, &t) == 0) 
     207            { 
     208                DEBUGP("using port %hu (1 of 2)\n", loport); 
     209                break; 
     210            } 
     211        } 
     212        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */ 
     213        { 
     214            t.dst.u.udp.port = htons(hiport); 
     215            if (ip_conntrack_change_expect(exp, &t) == 0) 
     216            { 
     217                DEBUGP("using port %hu (2 of 2)\n", hiport); 
     218                break; 
     219            } 
     220        } 
     221        if (loport != 0 && hiport != 0) 
     222        { 
     223            rbuf1len = sprintf(rbuf1, "%hu", loport); 
     224            if (hiport == loport+1) 
     225            { 
     226                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); 
     227            } 
     228            else 
     229            { 
     230                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport); 
     231            } 
     232        } 
     233        break; 
     234    } 
     235 
     236    if (rbuf1len == 0) 
     237    { 
     238        return 0;   /* cannot get replacement port(s) */ 
     239    } 
     240 
     241    /* Transport: tran;field;field=val,tran;field;field=val,... */ 
     242    while (off < tranlen) 
     243    { 
     244        uint        saveoff; 
     245        const char* pparamend; 
     246        uint        nextparamoff; 
     247 
     248        pparamend = memchr(ptran+off, ',', tranlen-off); 
     249        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; 
     250        nextparamoff = pparamend-ptcp; 
     251 
     252        /* 
     253         * We pass over each param twice.  On the first pass, we look for a 
     254         * destination= field.  It is handled by the security policy.  If it 
     255         * is present, allowed, and equal to our external address, we assume 
     256         * that STUN is being used and we leave the client_port= field alone. 
     257         */ 
     258        is_stun = 0; 
     259        saveoff = off; 
     260        while (off < nextparamoff) 
     261        { 
     262            const char* pfieldend; 
     263            uint        nextfieldoff; 
     264 
     265            pfieldend = memchr(ptran+off, ';', nextparamoff-off); 
     266            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; 
     267 
     268            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) 
     269            { 
     270                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) 
     271                { 
     272                    is_stun = 1; 
     273                } 
     274                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) 
     275                { 
     276                    diff = nextfieldoff-off; 
     277                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
     278                                                         off, diff, NULL, 0)) 
     279                    { 
     280                        /* mangle failed, all we can do is bail */ 
     281                        return 0; 
     282                    } 
     283                    get_skb_tcpdata(*pskb, &ptcp, &tcplen); 
     284                    ptran = ptcp+tranoff; 
     285                    tranlen -= diff; 
     286                    nextparamoff -= diff; 
     287                    nextfieldoff -= diff; 
     288                } 
     289            } 
     290 
     291            off = nextfieldoff; 
     292        } 
     293        if (is_stun) 
     294        { 
     295            continue; 
     296        } 
     297        off = saveoff; 
     298        while (off < nextparamoff) 
     299        { 
     300            const char* pfieldend; 
     301            uint        nextfieldoff; 
     302 
     303            pfieldend = memchr(ptran+off, ';', nextparamoff-off); 
     304            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; 
     305 
     306            if (strncmp(ptran+off, "client_port=", 12) == 0) 
     307            { 
     308                u_int16_t   port; 
     309                uint        numlen; 
     310                uint        origoff; 
     311                uint        origlen; 
     312                char*       rbuf    = rbuf1; 
     313                uint        rbuflen = rbuf1len; 
     314 
     315                off += 12; 
     316                origoff = (ptran-ptcp)+off; 
     317                origlen = 0; 
     318                numlen = nf_strtou16(ptran+off, &port); 
     319                off += numlen; 
     320                origlen += numlen; 
     321                if (port != prtspexp->loport) 
     322                { 
     323                    DEBUGP("multiple ports found, port %hu ignored\n", port); 
     324                } 
     325                else 
     326                { 
     327                    if (ptran[off] == '-' || ptran[off] == '/') 
     328                    { 
     329                        off++; 
     330                        origlen++; 
     331                        numlen = nf_strtou16(ptran+off, &port); 
     332                        off += numlen; 
     333                        origlen += numlen; 
     334                        rbuf = rbufa; 
     335                        rbuflen = rbufalen; 
     336                    } 
     337 
     338                    /* 
     339                     * note we cannot just memcpy() if the sizes are the same. 
     340                     * the mangle function does skb resizing, checks for a 
     341                     * cloned skb, and updates the checksums. 
     342                     * 
     343                     * parameter 4 below is offset from start of tcp data. 
     344                     */ 
     345                    diff = origlen-rbuflen; 
     346                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
     347                                              origoff, origlen, rbuf, rbuflen)) 
     348                    { 
     349                        /* mangle failed, all we can do is bail */ 
     350                        return 0; 
     351                    } 
     352                    get_skb_tcpdata(*pskb, &ptcp, &tcplen); 
     353                    ptran = ptcp+tranoff; 
     354                    tranlen -= diff; 
     355                    nextparamoff -= diff; 
     356                    nextfieldoff -= diff; 
     357                } 
     358            } 
     359 
     360            off = nextfieldoff; 
     361        } 
     362 
     363        off = nextparamoff; 
     364    } 
     365 
     366    return 1; 
     367} 
     368 
     369static unsigned int 
     370expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info) 
     371{ 
     372    struct ip_nat_multi_range mr; 
     373    u_int32_t newdstip, newsrcip, newip; 
     374 
     375    struct ip_conntrack *master = master_ct(ct); 
     376 
     377    IP_NF_ASSERT(info); 
     378    IP_NF_ASSERT(master); 
     379 
     380    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum)))); 
     381 
     382    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; 
     383    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; 
     384    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip; 
     385 
     386    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n", 
     387           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip)); 
     388 
     389    mr.rangesize = 1; 
     390    /* We don't want to manip the per-protocol, just the IPs. */ 
     391    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; 
     392    mr.range[0].min_ip = mr.range[0].max_ip = newip; 
     393 
     394    return ip_nat_setup_info(ct, &mr, hooknum); 
     395} 
     396 
     397static uint 
     398help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo, 
     399         struct ip_conntrack_expect* exp, struct sk_buff** pskb) 
     400{ 
     401    char*   ptcp; 
     402    uint    tcplen; 
     403    uint    hdrsoff; 
     404    uint    hdrslen; 
     405    uint    lineoff; 
     406    uint    linelen; 
     407    uint    off; 
     408 
     409    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; 
     410    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); 
     411 
     412    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info; 
     413 
     414    get_skb_tcpdata(*pskb, &ptcp, &tcplen); 
     415 
     416    hdrsoff = exp->seq - ntohl(tcph->seq); 
     417    hdrslen = prtspexp->len; 
     418    off = hdrsoff; 
     419 
     420    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) 
     421    { 
     422        if (linelen == 0) 
     423        { 
     424            break; 
     425        } 
     426        if (off > hdrsoff+hdrslen) 
     427        { 
     428            INFOP("!! overrun !!"); 
     429            break; 
     430        } 
     431        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); 
     432 
     433        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) 
     434        { 
     435            uint oldtcplen = tcplen; 
     436            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen)) 
     437            { 
     438                break; 
     439            } 
     440            get_skb_tcpdata(*pskb, &ptcp, &tcplen); 
     441            hdrslen -= (oldtcplen-tcplen); 
     442            off -= (oldtcplen-tcplen); 
     443            lineoff -= (oldtcplen-tcplen); 
     444            linelen -= (oldtcplen-tcplen); 
     445            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); 
     446        } 
     447    } 
     448 
     449    return NF_ACCEPT; 
     450} 
     451 
     452static uint 
     453help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo, 
     454         struct ip_conntrack_expect* exp, struct sk_buff** pskb) 
     455{ 
     456    /* XXX: unmangle */ 
     457    return NF_ACCEPT; 
     458} 
     459 
     460static uint 
     461help(struct ip_conntrack* ct, 
     462     struct ip_conntrack_expect* exp, 
     463     struct ip_nat_info* info, 
     464     enum ip_conntrack_info ctinfo, 
     465     unsigned int hooknum, 
     466     struct sk_buff** pskb) 
     467{ 
     468    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph; 
     469    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4); 
     470    uint datalen; 
     471    int dir; 
     472    struct ip_ct_rtsp_expect* ct_rtsp_info; 
     473    int rc = NF_ACCEPT; 
     474 
     475    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL) 
     476    { 
     477        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb); 
     478        return NF_ACCEPT; 
     479    } 
     480 
     481    ct_rtsp_info = &exp->help.exp_rtsp_info; 
     482 
     483    /* 
     484     * Only mangle things once: original direction in POST_ROUTING 
     485     * and reply direction on PRE_ROUTING. 
     486     */ 
     487    dir = CTINFO2DIR(ctinfo); 
     488    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL) 
     489          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) 
     490    { 
     491        DEBUGP("Not touching dir %s at hook %s\n", 
     492               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY", 
     493               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING" 
     494               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING" 
     495               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"); 
     496        return NF_ACCEPT; 
     497    } 
     498    DEBUGP("got beyond not touching\n"); 
     499 
     500    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; 
     501 
     502    LOCK_BH(&ip_rtsp_lock); 
     503    /* Ensure the packet contains all of the marked data */ 
     504    if (!between(exp->seq + ct_rtsp_info->len, 
     505                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen)) 
     506    { 
     507        /* Partial retransmission?  Probably a hacker. */ 
     508        if (net_ratelimit()) 
     509        { 
     510            INFOP("partial packet %u/%u in %u/%u\n", 
     511                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen); 
     512        } 
     513        UNLOCK_BH(&ip_rtsp_lock); 
     514        return NF_DROP; 
     515    } 
     516 
     517    switch (dir) 
     518    { 
     519    case IP_CT_DIR_ORIGINAL: 
     520        rc = help_out(ct, ctinfo, exp, pskb); 
     521        break; 
     522    case IP_CT_DIR_REPLY: 
     523        rc = help_in(ct, ctinfo, exp, pskb); 
     524        break; 
     525    } 
     526    UNLOCK_BH(&ip_rtsp_lock); 
     527 
     528    return rc; 
     529} 
     530 
     531static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS]; 
     532static char rtsp_names[MAX_PORTS][10]; 
     533 
     534/* This function is intentionally _NOT_ defined as  __exit */ 
     535static void 
     536fini(void) 
     537{ 
     538    int i; 
     539 
     540    for (i = 0; i < num_ports; i++) 
     541    { 
     542        DEBUGP("unregistering helper for port %d\n", ports[i]); 
     543        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]); 
     544    } 
     545} 
     546 
     547static int __init 
     548init(void) 
     549{ 
     550    int ret = 0; 
     551    int i; 
     552    struct ip_nat_helper* hlpr; 
     553    char* tmpname; 
     554 
     555    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); 
     556 
     557    if (ports[0] == 0) 
     558    { 
     559        ports[0] = RTSP_PORT; 
     560    } 
     561 
     562    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) 
     563    { 
     564        hlpr = &ip_nat_rtsp_helpers[i]; 
     565        memset(hlpr, 0, sizeof(struct ip_nat_helper)); 
     566 
     567        hlpr->tuple.dst.protonum = IPPROTO_TCP; 
     568        hlpr->tuple.src.u.tcp.port = htons(ports[i]); 
     569        hlpr->mask.src.u.tcp.port = 0xFFFF; 
     570        hlpr->mask.dst.protonum = 0xFFFF; 
     571        hlpr->help = help; 
     572        hlpr->flags = 0; 
     573        hlpr->me = THIS_MODULE; 
     574        hlpr->expect = expected; 
     575 
     576        tmpname = &rtsp_names[i][0]; 
     577        if (ports[i] == RTSP_PORT) 
     578        { 
     579                sprintf(tmpname, "rtsp"); 
     580        } 
     581        else 
     582        { 
     583                sprintf(tmpname, "rtsp-%d", i); 
     584        } 
     585        hlpr->name = tmpname; 
     586 
     587        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name); 
     588        ret = ip_nat_helper_register(hlpr); 
     589 
     590        if (ret) 
     591        { 
     592            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]); 
     593            fini(); 
     594            return 1; 
     595        } 
     596        num_ports++; 
     597    } 
     598    if (stunaddr != NULL) 
     599    { 
     600        extip = in_aton(stunaddr); 
     601    } 
     602    if (destaction != NULL) 
     603    { 
     604        if (strcmp(destaction, "auto") == 0) 
     605        { 
     606            dstact = DSTACT_AUTO; 
     607        } 
     608        if (strcmp(destaction, "strip") == 0) 
     609        { 
     610            dstact = DSTACT_STRIP; 
     611        } 
     612        if (strcmp(destaction, "none") == 0) 
     613        { 
     614            dstact = DSTACT_NONE; 
     615        } 
     616    } 
     617    return ret; 
     618} 
     619 
     620module_init(init); 
     621module_exit(fini); 
  • arch/mips/kernel/mips_ksyms.c

    diff -urN linux-2.4.30/arch/mips/kernel/mips_ksyms.c linux-2.4.30.new/arch/mips/kernel/mips_ksyms.c
    old new  
    4848/* 
    4949 * String functions 
    5050 */ 
     51EXPORT_SYMBOL_NOVERS(memchr); 
    5152EXPORT_SYMBOL_NOVERS(memcmp); 
    5253EXPORT_SYMBOL_NOVERS(memset); 
    5354EXPORT_SYMBOL_NOVERS(memcpy); 
  • include/linux/netfilter_helpers.h

    diff -urN linux-2.4.30/include/linux/netfilter_helpers.h linux-2.4.30.new/include/linux/netfilter_helpers.h
    old new  
     1/* 
     2 * Helpers for netfiler modules.  This file provides implementations for basic 
     3 * functions such as strncasecmp(), etc. 
     4 * 
     5 * gcc will warn for defined but unused functions, so we only include the 
     6 * functions requested.  The following macros are used: 
     7 *   NF_NEED_STRNCASECMP        nf_strncasecmp() 
     8 *   NF_NEED_STRTOU16           nf_strtou16() 
     9 *   NF_NEED_STRTOU32           nf_strtou32() 
     10 */ 
     11#ifndef _NETFILTER_HELPERS_H 
     12#define _NETFILTER_HELPERS_H 
     13 
     14/* Only include these functions for kernel code. */ 
     15#ifdef __KERNEL__ 
     16 
     17#include <linux/ctype.h> 
     18#define iseol(c) ( (c) == '\r' || (c) == '\n' ) 
     19 
     20/* 
     21 * The standard strncasecmp() 
     22 */ 
     23#ifdef NF_NEED_STRNCASECMP 
     24static int 
     25nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) 
     26{ 
     27    if (s1 == NULL || s2 == NULL) 
     28    { 
     29        if (s1 == NULL && s2 == NULL) 
     30        { 
     31            return 0; 
     32        } 
     33        return (s1 == NULL) ? -1 : 1; 
     34    } 
     35    while (len > 0 && tolower(*s1) == tolower(*s2)) 
     36    { 
     37        len--; 
     38        s1++; 
     39        s2++; 
     40    } 
     41    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); 
     42} 
     43#endif /* NF_NEED_STRNCASECMP */ 
     44 
     45/* 
     46 * Parse a string containing a 16-bit unsigned integer. 
     47 * Returns the number of chars used, or zero if no number is found. 
     48 */ 
     49#ifdef NF_NEED_STRTOU16 
     50static int 
     51nf_strtou16(const char* pbuf, u_int16_t* pval) 
     52{ 
     53    int n = 0; 
     54 
     55    *pval = 0; 
     56    while (isdigit(pbuf[n])) 
     57    { 
     58        *pval = (*pval * 10) + (pbuf[n] - '0'); 
     59        n++; 
     60    } 
     61 
     62    return n; 
     63} 
     64#endif /* NF_NEED_STRTOU16 */ 
     65 
     66/* 
     67 * Parse a string containing a 32-bit unsigned integer. 
     68 * Returns the number of chars used, or zero if no number is found. 
     69 */ 
     70#ifdef NF_NEED_STRTOU32 
     71static int 
     72nf_strtou32(const char* pbuf, u_int32_t* pval) 
     73{ 
     74    int n = 0; 
     75 
     76    *pval = 0; 
     77    while (pbuf[n] >= '0' && pbuf[n] <= '9') 
     78    { 
     79        *pval = (*pval * 10) + (pbuf[n] - '0'); 
     80        n++; 
     81    } 
     82 
     83    return n; 
     84} 
     85#endif /* NF_NEED_STRTOU32 */ 
     86 
     87/* 
     88 * Given a buffer and length, advance to the next line and mark the current 
     89 * line. 
     90 */ 
     91#ifdef NF_NEED_NEXTLINE 
     92static int 
     93nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) 
     94{ 
     95    uint    off = *poff; 
     96    uint    physlen = 0; 
     97 
     98    if (off >= len) 
     99    { 
     100        return 0; 
     101    } 
     102 
     103    while (p[off] != '\n') 
     104    { 
     105        if (len-off <= 1) 
     106        { 
     107            return 0; 
     108        } 
     109 
     110        physlen++; 
     111        off++; 
     112    } 
     113 
     114    /* if we saw a crlf, physlen needs adjusted */ 
     115    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') 
     116    { 
     117        physlen--; 
     118    } 
     119 
     120    /* advance past the newline */ 
     121    off++; 
     122 
     123    *plineoff = *poff; 
     124    *plinelen = physlen; 
     125    *poff = off; 
     126 
     127    return 1; 
     128} 
     129#endif /* NF_NEED_NEXTLINE */ 
     130 
     131#endif /* __KERNEL__ */ 
     132 
     133#endif /* _NETFILTER_HELPERS_H */ 
  • include/linux/netfilter_ipv4/ip_conntrack_rtsp.h

    diff -urN linux-2.4.30/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.4.30.new/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
    old new  
     1/* 
     2 * RTSP extension for IP connection tracking. 
     3 * (C) 2003 by Tom Marshall <tmarshall@real.com> 
     4 * based on ip_conntrack_irc.h 
     5 * 
     6 *      This program is free software; you can redistribute it and/or 
     7 *      modify it under the terms of the GNU General Public License 
     8 *      as published by the Free Software Foundation; either version 
     9 *      2 of the License, or (at your option) any later version. 
     10 */ 
     11#ifndef _IP_CONNTRACK_RTSP_H 
     12#define _IP_CONNTRACK_RTSP_H 
     13 
     14/* #define IP_NF_RTSP_DEBUG */ 
     15#define IP_NF_RTSP_VERSION "0.01" 
     16 
     17/* port block types */ 
     18typedef enum { 
     19    pb_single,  /* client_port=x */ 
     20    pb_range,   /* client_port=x-y */ 
     21    pb_discon   /* client_port=x/y (rtspbis) */ 
     22} portblock_t; 
     23 
     24/* We record seq number and length of rtsp headers here, all in host order. */ 
     25 
     26/* 
     27 * This structure is per expected connection.  It is a member of struct 
     28 * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored 
     29 * there and we are expected to only store the length of the data which 
     30 * needs replaced.  If a packet contains multiple RTSP messages, we create 
     31 * one expected connection per message. 
     32 * 
     33 * We use these variables to mark the entire header block.  This may seem 
     34 * like overkill, but the nature of RTSP requires it.  A header may appear 
     35 * multiple times in a message.  We must treat two Transport headers the 
     36 * same as one Transport header with two entries. 
     37 */ 
     38struct ip_ct_rtsp_expect 
     39{ 
     40    u_int32_t   len;        /* length of header block */ 
     41    portblock_t pbtype;     /* Type of port block that was requested */ 
     42    u_int16_t   loport;     /* Port that was requested, low or first */ 
     43    u_int16_t   hiport;     /* Port that was requested, high or second */ 
     44#if 0 
     45    uint        method;     /* RTSP method */ 
     46    uint        cseq;       /* CSeq from request */ 
     47#endif 
     48}; 
     49 
     50/* This structure exists only once per master */ 
     51struct ip_ct_rtsp_master 
     52{ 
     53    /* Empty (?) */ 
     54}; 
     55 
     56 
     57#ifdef __KERNEL__ 
     58 
     59#include <linux/netfilter_ipv4/lockhelp.h> 
     60 
     61#define RTSP_PORT   554 
     62 
     63/* Protects rtsp part of conntracks */ 
     64DECLARE_LOCK_EXTERN(ip_rtsp_lock); 
     65 
     66#endif /* __KERNEL__ */ 
     67 
     68#endif /* _IP_CONNTRACK_RTSP_H */ 
  • include/linux/netfilter_mime.h

    diff -urN linux-2.4.30/include/linux/netfilter_mime.h linux-2.4.30.new/include/linux/netfilter_mime.h
    old new  
     1/* 
     2 * MIME functions for netfilter modules.  This file provides implementations 
     3 * for basic MIME parsing.  MIME headers are used in many protocols, such as 
     4 * HTTP, RTSP, SIP, etc. 
     5 * 
     6 * gcc will warn for defined but unused functions, so we only include the 
     7 * functions requested.  The following macros are used: 
     8 *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline() 
     9 */ 
     10#ifndef _NETFILTER_MIME_H 
     11#define _NETFILTER_MIME_H 
     12 
     13/* Only include these functions for kernel code. */ 
     14#ifdef __KERNEL__ 
     15 
     16#include <linux/kernel.h> 
     17#include <linux/ctype.h> 
     18 
     19/* 
     20 * Given a buffer and length, advance to the next line and mark the current 
     21 * line.  If the current line is empty, *plinelen will be set to zero.  If 
     22 * not, it will be set to the actual line length (including CRLF). 
     23 * 
     24 * 'line' in this context means logical line (includes LWS continuations). 
     25 * Returns 1 on success, 0 on failure. 
     26 */ 
     27#ifdef NF_NEED_MIME_NEXTLINE 
     28static int 
     29nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) 
     30{ 
     31    uint    off = *poff; 
     32    uint    physlen = 0; 
     33    int     is_first_line = 1; 
     34 
     35    if (off >= len) 
     36    { 
     37        return 0; 
     38    } 
     39 
     40    do 
     41    { 
     42        while (p[off] != '\n') 
     43        { 
     44            if (len-off <= 1) 
     45            { 
     46                return 0; 
     47            } 
     48 
     49            physlen++; 
     50            off++; 
     51        } 
     52 
     53        /* if we saw a crlf, physlen needs adjusted */ 
     54        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') 
     55        { 
     56            physlen--; 
     57        } 
     58 
     59        /* advance past the newline */ 
     60        off++; 
     61 
     62        /* check for an empty line */ 
     63        if (physlen == 0) 
     64        { 
     65            break; 
     66        } 
     67 
     68        /* check for colon on the first physical line */ 
     69        if (is_first_line) 
     70        { 
     71            is_first_line = 0; 
     72            if (memchr(p+(*poff), ':', physlen) == NULL) 
     73            { 
     74                return 0; 
     75            } 
     76        } 
     77    } 
     78    while (p[off] == ' ' || p[off] == '\t'); 
     79 
     80    *plineoff = *poff; 
     81    *plinelen = (physlen == 0) ? 0 : (off - *poff); 
     82    *poff = off; 
     83 
     84    return 1; 
     85} 
     86#endif /* NF_NEED_MIME_NEXTLINE */ 
     87 
     88#endif /* __KERNEL__ */ 
     89 
     90#endif /* _NETFILTER_MIME_H */ 
Note: See TracBrowser for help on using the repository browser.