示例#1
0
void rtsp_parse_line(RTSPHeader *reply, const char *buf)
{
    const char *p;

    /* NOTE: we do case independent match for broken servers */
    p = buf;
    if (stristart(p, "Session:", &p)) {
        get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
    } else if (stristart(p, "Content-Length:", &p)) {
        reply->content_length = strtol(p, NULL, 10);
    } else if (stristart(p, "Transport:", &p)) {
        rtsp_parse_transport(reply, p);
    } else if (stristart(p, "CSeq:", &p)) {
        reply->seq = strtol(p, NULL, 10);
    } else if (stristart(p, "Range:", &p)) {
        rtsp_parse_range_npt(reply, p);
    }
}
/* outbound packet: client->server */
static inline int
help_out(struct sk_buff **pskb, unsigned char *rb_ptr, unsigned int datalen,
                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
{
    struct ip_ct_rtsp_expect expinfo;
    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
    //struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
    //uint    tcplen = pktlen - iph->ihl * 4;
    char*   pdata = rb_ptr;
    //uint    datalen = tcplen - tcph->doff * 4;
    uint    dataoff = 0;
    int ret = NF_ACCEPT;

    struct ip_conntrack_expect *exp;

    memset(&expinfo, 0, sizeof(expinfo));

    while (dataoff < datalen)
    {
        uint    cmdoff = dataoff;
        uint    hdrsoff = 0;
        uint    hdrslen = 0;
        uint    cseqoff = 0;
        uint    cseqlen = 0;
        uint    lineoff = 0;
        uint    linelen = 0;
        uint    off;

        if (!rtsp_parse_message(pdata, datalen, &dataoff,
                                &hdrsoff, &hdrslen,
                                &cseqoff, &cseqlen))
        {
            break;      /* not a valid message */
        }

        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
        {
            continue;   /* not a SETUP message */
        }
        DEBUGP("found a setup message\n");

        off = 0;
        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
                                &lineoff, &linelen))
        {
            if (linelen == 0)
            {
                break;
            }
            if (off > hdrsoff+hdrslen)
            {
                INFOP("!! overrun !!");
                break;
            }

            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
            {
                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen, &expinfo);
            }
        }

        if (expinfo.loport == 0)
        {
            DEBUGP("no udp transports found\n");
            continue;   /* no udp transports found */
        }

        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
              (int)expinfo.pbtype,
              expinfo.loport,
              expinfo.hiport);

	exp = ip_conntrack_expect_alloc(ct);
	if (!exp) {
		ret = NF_DROP;
		goto out;
	}

        //exp->seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
	exp->master = ct;
        //exp.help.exp_rtsp_info.len = hdrslen;

        exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
        exp->mask.src.ip  = 0xffffffff;
        exp->tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
        exp->mask.dst.ip  = 0xffffffff;
        exp->tuple.dst.u.udp.port = expinfo.loport;
        exp->mask.dst.u.udp.port  = 
		(expinfo.pbtype == pb_range) ? 0xfffe : 0xffff;
        exp->tuple.dst.protonum = IPPROTO_UDP;
        exp->mask.dst.protonum  = 0xff;

        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
                NIPQUAD(exp->tuple.src.ip),
                ntohs(exp->tuple.src.u.tcp.port),
                NIPQUAD(exp->tuple.dst.ip),
                ntohs(exp->tuple.dst.u.tcp.port));

	if (ip_nat_rtsp_hook)
        	/* pass the request off to the nat helper */
		ret = ip_nat_rtsp_hook(pskb, ctinfo, &expinfo, exp);
	else if (ip_conntrack_expect_related(exp) != 0) {
  		INFOP("ip_conntrack_expect_related failed\n");
		ip_conntrack_expect_put(exp);
		ret  = NF_DROP;
	}
	goto out;
    }
out:

    return ret;
}
示例#3
0
static inline int
help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen,
                struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
	struct ip_ct_rtsp_expect expinfo;
	
	int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
	//struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
	//uint    tcplen = pktlen - iph->ihl * 4;
	char*   pdata = rb_ptr;
	//uint    datalen = tcplen - tcph->doff * 4;
	uint    dataoff = 0;
	int ret = NF_ACCEPT;
	
	struct nf_conntrack_expect *exp;
	
	__be16 be_loport;
	
	typeof(nf_nat_rtsp_hook) nf_nat_rtsp;

	memset(&expinfo, 0, sizeof(expinfo));
	
	while (dataoff < datalen) {
		uint    cmdoff = dataoff;
		uint    hdrsoff = 0;
		uint    hdrslen = 0;
		uint    cseqoff = 0;
		uint    cseqlen = 0;
		uint    transoff = 0;
		uint    translen = 0;
		uint    off;
		
		if (!rtsp_parse_message(pdata, datalen, &dataoff,
					&hdrsoff, &hdrslen,
					&cseqoff, &cseqlen,
					&transoff, &translen))
			break;      /* not a valid message */
		
		if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
			continue;   /* not a SETUP message */
		pr_debug("found a setup message\n");

		off = 0;
		if(translen) {
			rtsp_parse_transport(pdata+transoff, translen, &expinfo);
		}

		if (expinfo.loport == 0) {
			pr_debug("no udp transports found\n");
			continue;   /* no udp transports found */
		}

		pr_debug("udp transport found, ports=(%d,%hu,%hu)\n",
		       (int)expinfo.pbtype, expinfo.loport, expinfo.hiport);

		exp = nf_ct_expect_alloc(ct);
		if (!exp) {
			ret = NF_DROP;
			goto out;
		}

		be_loport = htons(expinfo.loport);

		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
			/* media stream source can be different from the RTSP server address */
			// &ct->tuplehash[!dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3,
			NULL, &ct->tuplehash[!dir].tuple.dst.u3,
			IPPROTO_UDP, NULL, &be_loport); 

		exp->master = ct;

		exp->expectfn = expected;
		exp->flags = 0;

		if (expinfo.pbtype == pb_range) {
			pr_debug("Changing expectation mask to handle multiple ports\n");
			//exp->mask.dst.u.udp.port  = 0xfffe;
		}

		pr_debug("expect_related %pI4:%u-%pI4:%u\n",
		       &exp->tuple.src.u3.ip,
		       ntohs(exp->tuple.src.u.udp.port),
		       &exp->tuple.dst.u3.ip,
		       ntohs(exp->tuple.dst.u.udp.port));

		nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook);
		if (nf_nat_rtsp && ct->status & IPS_NAT_MASK)
			/* pass the request off to the nat helper */
			ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, &expinfo, exp);
		else if (nf_ct_expect_related(exp) != 0) {
			pr_info("nf_conntrack_expect_related failed\n");
			ret  = NF_DROP;
		}
		nf_ct_expect_put(exp);
		goto out;
	}
out:

	return ret;
}
示例#4
0
static inline int
help_out(struct sk_buff **pskb, unsigned char *rb_ptr, unsigned int datalen,
                struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
	struct ip_ct_rtsp_expect expinfo;

	int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
	//struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
	//uint    tcplen = pktlen - iph->ihl * 4;
	char*   pdata = rb_ptr;
	//uint    datalen = tcplen - tcph->doff * 4;
	uint    dataoff = 0;
	int ret = NF_ACCEPT;

	struct nf_conntrack_expect *exp;

	__be16 be_loport;

	typeof(nf_nat_rtsp_hook) nf_nat_rtsp;

	memset(&expinfo, 0, sizeof(expinfo));

	while (dataoff < datalen) {
		uint    cmdoff = dataoff;
		uint    hdrsoff = 0;
		uint    hdrslen = 0;
		uint    cseqoff = 0;
		uint    cseqlen = 0;
		uint    transoff = 0;
		uint    translen = 0;
		uint    off;

		if (!rtsp_parse_message(pdata, datalen, &dataoff,
					&hdrsoff, &hdrslen,
					&cseqoff, &cseqlen,
					&transoff, &translen))
			break;      /* not a valid message */

		if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
			continue;   /* not a SETUP message */
		pr_debug("found a setup message\n");

		off = 0;
		if(translen) {
			rtsp_parse_transport(pdata+transoff, translen, &expinfo);
		}

		if (expinfo.loport == 0) {
			pr_debug("no udp transports found\n");
			continue;   /* no udp transports found */
		}

		pr_debug("udp transport found, ports=(%d,%hu,%hu)\n",
		       (int)expinfo.pbtype, expinfo.loport, expinfo.hiport);

		exp = nf_conntrack_expect_alloc(ct);
		if (!exp) {
			ret = NF_DROP;
			goto out;
		}

		be_loport = htons(expinfo.loport);
/*
		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
			&ct->tuplehash[!dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3,
			IPPROTO_UDP, NULL, &be_loport);
           ¸øexp¸³Öµ  */
        exp->tuple.dst.u3 = ct->tuplehash[!dir].tuple.dst.u3;
        exp->tuple.src.u3 = ct->tuplehash[!dir].tuple.src.u3;
        exp->tuple.src.l3num = ct->tuplehash[dir].tuple.src.l3num;
        exp->tuple.src.u.udp.port = 0;
        exp->tuple.dst.u.udp.port = be_loport;
        exp->tuple.dst.protonum = IPPROTO_UDP;

        exp->mask = (struct nf_conntrack_tuple)
                { .src = { .l3num = 0xFFFF,
                       .u = { .udp = { 0 }},
                     },
                  .dst = { .protonum = 0xFF,
                       .u = { .udp = { __constant_htons(0xFFFF) }},
                     },
                };
        if (ct->tuplehash[dir].tuple.src.l3num == PF_INET) {
            exp->mask.src.u3.ip = htonl(0xFFFFFFFF);
            exp->mask.dst.u3.ip = htonl(0xFFFFFFFF);
        } else {
            memset(exp->mask.src.u3.ip6, 0xFF,
                   sizeof(exp->mask.src.u3.ip6));
            memset(exp->mask.dst.u3.ip6, 0xFF,
                   sizeof(exp->mask.src.u3.ip6));
        }
	//	exp->master = ct;
        exp->helper = NULL;
		exp->flags = 0;

		if (expinfo.pbtype == pb_range) {
			pr_debug("Changing expectation mask to handle multiple ports\n");
			//exp->mask.dst.u.udp.port  = 0xfffe;
		}

		pr_debug("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
		       NIPQUAD(exp->tuple.src.u3.ip),
		       ntohs(exp->tuple.src.u.udp.port),
		       NIPQUAD(exp->tuple.dst.u3.ip),
		       ntohs(exp->tuple.dst.u.udp.port));

		nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook);
		if (nf_nat_rtsp && ct->status & IPS_NAT_MASK)
			/* pass the request off to the nat helper */
			ret = nf_nat_rtsp(pskb, ctinfo, hdrsoff, hdrslen, &expinfo, exp);
		else if (nf_conntrack_expect_related(exp) != 0) {
			pr_info("nf_conntrack_expect_related failed\n");
			ret  = NF_DROP;
		}
		nf_conntrack_expect_put(exp);
		goto out;
	}