H.225 parser for h323-conntrack-nat
PATCH 1/1 H.225 parser for h323-conntrack-nat
Hi,
this patch implements a "real" H.225 parser, replacing the old "brute force" algorithm. This parser is not complete yet; it currently only handles CONNECT packets, although that seems to be enough for most H.323 clients. I tested with ohphone, MS Netmeeting and gnomemeeting (plus a nfsim test which I will publish soon). NAT works well.
I havn't written a H.245 parser yet, that's the next item on my todo list.
The attached patch applies to the pom-ng trunk after you merged my last patches from the linux-2.6.11 branch:
cd h323-conntrack-nat/linux-2.6.11
svn merge -r 3689:3690 \
https://svn.netfilter.org/netfilter/branches/patch-o-matic-ng/linux-2.6.11/h323-conntrack-nat/linux-2.6(I guess the linux-2.6.11 branch is obsolete since the h323-conntrack-nat/linux-2.6.11 directory was introduced by Harald)
Max
Thu Mar 17 04:05:23 CET 2005 [email protected]
* replaced brute force by a H.225 parser, still incomplete
h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323.c +197 -75
@@ -178,21 +178,204 @@WRITE_UNLOCK (&ip_conntrack_lock); } -/* FIXME: This should be in userspace. Later. */ +/** +* Parse a Q.931 CONNECT packet and handle NAT/expectations for the +* H.245 transport address. +*/ +static int h225_parse_q931_connect (struct sk_buff **pskb, +struct ip_conntrack *ct, +enum ip_conntrack_info ctinfo, +const unsigned char *data, +unsigned i,unsigned length) +{ +int dir =CTINFO2DIR (ctinfo); +u_int32_t data_ip; +u_int16_t data_port; +struct ip_conntrack_expect *exp; + +/* protocol(1) + header(3) + protocolIdentifier(6) + +h245ipAddress(1) + h245ipv4(4) + h245ipv4port(2) */ +if (length <17 ) +return NF_ACCEPT ; + +if (data[i++] !=0x05 )/* X.208 / X.209 */ +return NF_ACCEPT ; + +/* XXX: h225 header connect? */ +if (data[i++] !=0x22 || data[i++] !=0xc0 || data[i++] !=0x06 ) +return NF_ACCEPT ; + +/* protocolIdentifier, ignore the last 2 bytes (minor +version) */ +if (memcmp (data + i,"\x00\x08\x91\x4a" ,4 ) !=0 ) +return NF_ACCEPT ; + + i +=6 ; + +if (data[i++] !=0x00 )/* h245ipAddress? */ +return NF_ACCEPT ; + +/* compare the IP address - this is only a valid H.245 +transport address, if it equals the source address of the +packet */ + data_ip = *(u_int32_t *)(data + i); +if (data_ip != ct->tuplehash[dir].tuple.src.ip) +return NF_ACCEPT ; + + + data_port = *((u_int16_t *)(data + i +4 )); + +/* match found: create an expectation */ + exp =ip_conntrack_expect_alloc (); +if (exp ==NULL ) +return NF_ACCEPT ; + + exp->tuple = ((struct ip_conntrack_tuple ) + { { ct->tuplehash[!dir].tuple.src.ip, + {0 } }, + { ct->tuplehash[!dir].tuple.dst.ip, + { .tcp = { data_port } }, +IPPROTO_TCP }}); + exp->mask = ((struct ip_conntrack_tuple ) + { {0xFFFFFFFF , {0 } }, + {0xFFFFFFFF , { .tcp = {0xFFFF } },0xFF }}); + + exp->expectfn = h225_expect; + exp->master = ct; + +/* call NAT hook and register expectation */ +if (ip_nat_h225_hook !=NULL ) { +return ip_nat_h225_hook (pskb, ctinfo, i, + exp); + }else { +/* Can't expect this? Best to drop packet now. */ +if (ip_conntrack_expect_related (exp) !=0 ) { +ip_conntrack_expect_free (exp); +return NF_DROP ; + }else { +return NF_ACCEPT ; + } + } +} + +/** +* Scan a Q.931 packet for a user-to-user information element +* (IE). Return the index, or 0 if none found. +*/ +static unsigned q931_find_u2u (const unsigned char *data, +unsigned datalen, +unsigned int i, +unsigned *lengthp) { +unsigned char type; +unsigned length; + +/* traverse all Q.931 information elements (IE) */ +while (i +2 <= datalen) { + type = data[i++]; + +/* highest bit set means one-byte IE */ +if (type &0x80 ) +continue ; + + length = data[i++]; + +if (type ==0x7e ) {/* user-to-user */ +/* user-to-user IEs have a 16 bit length +field */ + length = (length <<8 ) | data[i++]; +if (i + length > datalen) +return 0 ; + + *lengthp = length; +return i; + } + + i += length; + } + +return 0 ; +} + +/** +* Parse a Q.931/H.225 packet and handle NAT/expectations for the +* H.245 transport address (if applicable). +*/ +static int h225_parse_q931 (struct sk_buff **pskb, +struct ip_conntrack *ct, +enum ip_conntrack_info ctinfo, +const unsigned char *data, +unsigned datalen,unsigned i) { +u_int8_t q931_message_type; +unsigned length; + +/* parse Q.931 packet */ +if (data[i++] !=0x08 )/* protocol discriminator */ +return NF_ACCEPT ; + +/* call reference */ + i +=1 + data[i]; +if (i >= datalen) +return NF_ACCEPT ; + +/* only some Q.931 message types can contain a H.245 transport +address - we can ignore the rest in this module */ + q931_message_type = data[i++]; +if (q931_message_type ==0x07 ) { +/* CONNECT */ + +/* find a user-to-user information element (IE) */ + i =q931_find_u2u (data, datalen, i, &length); +if (i ==0 ) +return NF_ACCEPT ; + +return h225_parse_q931_connect (pskb, ct, ctinfo, + data, i, length); + }else { +/* XXX handle q931_message_type 0x01, 0x02, 0x03 */ +return NF_ACCEPT ; + } +} + +/** +* Parse a TPKT/Q.931/H.225 packet and handle NAT/expectations for the +* H.245 transport address (if applicable). +*/ +static int h225_parse_tpkt (struct sk_buff **pskb, +struct ip_conntrack *ct, +enum ip_conntrack_info ctinfo, +const unsigned char *data, +unsigned datalen) { +unsigned int i =0 ; +u_int16_t tpkt_len; + +/* expect TPKT header, see RFC 1006 */ +if (data[0 ] !=0x03 || data[1 ] !=0x00 ) +return NF_ACCEPT ; + + i +=2 ; + + tpkt_len =ntohs (*(u_int16_t *)(data + i)); +if (tpkt_len <16 ) +return NF_ACCEPT ; + +if (tpkt_len < datalen) + datalen = tpkt_len; + + i +=2 ; + +/* parse Q.931 packet */ +return h225_parse_q931 (pskb, ct, ctinfo, + data, datalen, i); +} +static int h225_help (struct sk_buff **pskb,struct ip_conntrack *ct,enum ip_conntrack_info ctinfo) {struct tcphdr _tcph, *tcph;unsigned char *data; -unsigned char *data_limit;unsigned dataoff, datalen; -int dir =CTINFO2DIR (ctinfo); -struct ip_conntrack_expect *exp; -u_int16_t data_port; -u_int32_t data_ip; -unsigned int i; -int ret; +int ret =NF_ACCEPT ;/* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED
@@ -218,79 +401,18 @@ } datalen = (*pskb)->len - dataoff; +if (datalen <32 ) +return NF_ACCEPT ; + +/* get data portion, and evaluate it */ LOCK_BH (&ip_h323_lock); data =skb_header_pointer ((*pskb), dataoff, datalen, h323_buffer);BUG_ON (data ==NULL ); - data_limit = data + datalen -6 ; -/* bytes: 0123 45 -ipadrr port */ -for (i =0 ; data <= data_limit; data++, i++) { - data_ip = *((u_int32_t *)data); -if (data_ip == ct->tuplehash[dir].tuple.src.ip) { - data_port = *((u_int16_t *)(data +4 )); -if (data_port == ct->tuplehash[dir].tuple.src.u.tcp.port) { -/* Signal address */ -DEBUGP ("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n" , -NIPQUAD ((*pskb)->nh.iph->saddr)); -/* Update the H.225 info so that NAT can mangle the address/port -even when we have no expected connection! */ -if (ip_nat_h225_signal_hook !=NULL ) -ip_nat_h225_signal_hook (pskb, ct, ctinfo, - i,IP_CT_DIR_ORIGINAL , dir); - }else { -/* update the H.225 info */ - exp =ip_conntrack_expect_alloc (); -if (exp ==NULL ) { - ret =NF_ACCEPT ; - goto out; - } - - exp->tuple = ((struct ip_conntrack_tuple ) - { { ct->tuplehash[!dir].tuple.src.ip, - {0 } }, - { data_ip, - { .tcp = { data_port } }, -IPPROTO_TCP }}); - exp->mask = ((struct ip_conntrack_tuple ) - { {0xFFFFFFFF , {0 } }, - {0xFFFFFFFF , { .tcp = {0xFFFF } },0xFF }}); - - exp->expectfn = h225_expect; - exp->master = ct; - -if (ip_nat_h225_hook !=NULL ) { - ret =ip_nat_h225_hook (pskb, ctinfo, i, - exp); - }else { -/* Can't expect this? Best to drop packet now. */ -if (ip_conntrack_expect_related (exp) !=0 ) { -ip_conntrack_expect_free (exp); - ret =NF_DROP ; - }else - ret =NF_ACCEPT ; - } - } - -break ; - }else if (data_ip == ct->tuplehash[dir].tuple.dst.ip) { - data_port = *((u_int16_t *)(data +4 )); -if (data_port == ct->tuplehash[dir].tuple.dst.u.tcp.port) { -/* Signal address */ -DEBUGP ("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n" , -NIPQUAD ((*pskb)->nh.iph->daddr)); -/* Update the H.225 info so that NAT can mangle the address/port -even when we have no expected connection! */ -if (ip_nat_h225_signal_hook !=NULL ) -ip_nat_h225_signal_hook (pskb, ct, ctinfo, - i,IP_CT_DIR_REPLY , dir); - } - } - } + ret =h225_parse_tpkt (pskb, ct, ctinfo, + data, datalen); - ret =NF_ACCEPT ; - out:UNLOCK_BH (&ip_h323_lock);return ret; }
Quoted 7 lines · Max Kellermann
Hi,
this patch implements a "real" H.225 parser, replacing the old "brute force" algorithm. This parser is not complete yet; it currently only handles CONNECT packets, although that seems to be enough for most H.323 clients. I tested with ohphone, MS Netmeeting and gnomemeeting (plus a nfsim test which I will publish soon). NAT works well.
First of all, thanks for your excellent work on this. However, I'm not sure whether to apply the patch, since I don't have any test setup for h.323.
Jozsef: what do you think of that patch? h.323 helper is your code, after all.
If your nfsim patch could be merged, that would help a lot.
Quoted 2 lines
I havn't written a H.245 parser yet, that's the next item on my todo list.
Great, need to read through the rest of my two week email backlog in order to see whether that was already finished and sent to the list :)
Quoted 2 lines
(I guess the linux-2.6.11 branch is obsolete since the h323-conntrack-nat/linux-2.6.11 directory was introduced by Harald)
exactly.
Quoted 1 line
Max
Signature · 5 lines
- Harald Welte <[email protected]> http://netfilter.org/ ============================================================================ "Fragmentation is like classful addressing -- an interesting early architectural error that shows how much experimentation was going on while IP was being designed." -- Paul Vixie
Hi,
Quoted 7 lines · Harald Welte
Quoted 5 lines · Max Kellermann
this patch implements a "real" H.225 parser, replacing the old "brute force" algorithm. This parser is not complete yet; it currently only handles CONNECT packets, although that seems to be enough for most H.323 clients. I tested with ohphone, MS Netmeeting and gnomemeeting (plus a nfsim test which I will publish soon). NAT works well.
Quoted 6 lines
First of all, thanks for your excellent work on this. However, I'm not sure whether to apply the patch, since I don't have any test setup for h.323.
Jozsef: what do you think of that patch? h.323 helper is your code, after all.
Max does the right thing. And as he completes the helper with the H.245 parser, we could finally consider to push the helper into the kernel. :-)
Best regards,
Jozsef
-
E-mail : [email protected], [email protected] PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
H-1525 Budapest 114, POB. 49, Hungary
Hi all,
back from vacation now.
Quoted 6 lines · Jozsef Kadlecsik
Quoted 2 lines
Jozsef: what do you think of that patch? h.323 helper is your code, after all.
Max does the right thing. And as he completes the helper with the H.245 parser, we could finally consider to push the helper into the kernel. :-)
Jozsef, thanks for confirming my patches. The H.225 parser works for the clients I tested, but needs more work, because it *may* break other clients (no ASN.1-PER parser, just q'n'd).
I have already written a lean H.245 parser which is working for me. It aims to parse the ASN.1-PER correctly, but it has grown more complex than I had expected. I will release it after I have spent more time on cleanup, review and testing.
Security is my goal #1; what we need least is a remote kernel hole (other ASN.1 parsers had holes in the past). This is the most complex conntrack helper until now. It has to undergo much more review before we can recommend it for the mainstream kernel.
Once the H.245 parser is finished, the H.225 parser will be rewritten using my low-level ASN.1-PER parser library.
Max
Hi Max,
Quoted 11 lines · Max Kellermann
Quoted 6 lines · Jozsef Kadlecsik
Quoted 2 lines
Jozsef: what do you think of that patch? h.323 helper is your code, after all.
Max does the right thing. And as he completes the helper with the H.245 parser, we could finally consider to push the helper into the kernel. :-)
Jozsef, thanks for confirming my patches. The H.225 parser works for the clients I tested, but needs more work, because it *may* break other clients (no ASN.1-PER parser, just q'n'd).
It *is* a big step ahead: no more guesswork but parsing. The protocols behind H.323 plus the underlying ASN.1 coding create a nigthmare and I'm really impressed someone finally stepped ahead to cope with it.
Quoted 9 lines
I have already written a lean H.245 parser which is working for me. It aims to parse the ASN.1-PER correctly, but it has grown more complex than I had expected. I will release it after I have spent more time on cleanup, review and testing.
Security is my goal #1; what we need least is a remote kernel hole (other ASN.1 parsers had holes in the past). This is the most complex conntrack helper until now. It has to undergo much more review before we can recommend it for the mainstream kernel.
Exactly. Therefore I'd prefer nfsim tests, which do not only check the functionality but violate the specifications and the parser in the helper at the cricital points.
Quoted 2 lines
Once the H.245 parser is finished, the H.225 parser will be rewritten using my low-level ASN.1-PER parser library.
Best regards,
Jozsef
-
E-mail : [email protected], [email protected] PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
H-1525 Budapest 114, POB. 49, Hungary
Hi Max Kellermann,
It is very good news for me.
Please read back to my mail titled as "Need help on 2.6.11 and pom-ng HEAD"
I want to make it works under 2.6.11 or 2.6.12. I really need your help to finish it in time.
I will spend a day (ideally) to look into the new conntrack infrastructure, and then I will spend time on every conntrack involved. If the old code works, I think it is not very hard to port them to new infrastructure. provided that new infrastruture is stable and good.
Quoted 31 lines · Max Kellermann
Hi all,
back from vacation now.
Quoted 6 lines · Jozsef Kadlecsik
Quoted 2 lines
Jozsef: what do you think of that patch? h.323 helper is your code, after all.
Max does the right thing. And as he completes the helper with the H.245 parser, we could finally consider to push the helper into the kernel. :-)
Jozsef, thanks for confirming my patches. The H.225 parser works for the clients I tested, but needs more work, because it *may* break other clients (no ASN.1-PER parser, just q'n'd).
I have already written a lean H.245 parser which is working for me. It aims to parse the ASN.1-PER correctly, but it has grown more complex than I had expected. I will release it after I have spent more time on cleanup, review and testing.
Security is my goal #1; what we need least is a remote kernel hole (other ASN.1 parsers had holes in the past). This is the most complex conntrack helper until now. It has to undergo much more review before we can recommend it for the mainstream kernel.
Once the H.245 parser is finished, the H.225 parser will be rewritten using my low-level ASN.1-PER parser library.
Max
Signature · 1 line
lark
On 2005/04/04 16:01, Wang Jian <[email protected]> wrote:
[...]
Quoted 7 lines
I want to make it works under 2.6.11 or 2.6.12. I really need your help to finish it in time.
I will spend a day (ideally) to look into the new conntrack infrastructure, and then I will spend time on every conntrack involved. If the old code works, I think it is not very hard to port them to new infrastructure. provided that new infrastruture is stable and good.
I already ported h323-conntrack-nat to 2.6.11, but my port is hidden in an obsolete branch in the pom-ng svn repository. Please grab my patch from my home page:
http://max.kellermann.name/projects/netfilter/h323.html
This allows you to use h323-conntrack-nat on 2.6.11. The patches will be in the subversion repository soon (as discussed in this thread).
Max
Hi Max Kellermann,
I tried it once with 2.6.11 and 2.6.11.6, both failed. But I will try it again tomorrow.
Thanks.
Quoted 20 lines · Max Kellermann
On 2005/04/04 16:01, Wang Jian <[email protected]> wrote:
[...]Quoted 7 lines
I want to make it works under 2.6.11 or 2.6.12. I really need your help to finish it in time.
I will spend a day (ideally) to look into the new conntrack infrastructure, and then I will spend time on every conntrack involved. If the old code works, I think it is not very hard to port them to new infrastructure. provided that new infrastruture is stable and good.
I already ported h323-conntrack-nat to 2.6.11, but my port is hidden in an obsolete branch in the pom-ng svn repository. Please grab my patch from my home page:
http://max.kellermann.name/projects/netfilter/h323.html
This allows you to use h323-conntrack-nat on 2.6.11. The patches will be in the subversion repository soon (as discussed in this thread).
Max
Signature · 1 line
lark
Quoted 2 lines · Wang Jian
I tried it once with 2.6.11 and 2.6.11.6, both failed. But I will try it again tomorrow.
What failed exactly? Message? Reject file?
I guess changing the "time" parameter (= tomorrow) won't help in this case ;)
Max
Hi Max Kellermann,
Error message
Do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] y
unable to find ladd slot in src /tmp/pom-10691/include/linux/netfilter_ipv4/ip_conntrack.h (./h323-conntrack-nat/linux-2.6.11/./include/linux/netfilter_ipv4/ip_conntrack.h.ladd_3)
ladd_3 looks like
/* insert conntrack helper private data (expect) here */
struct ip_ct_h225_expect exp_h225_info;But ip_conntrac.h in 2.6.11 and 2.6.11.6 is
-- snip --
union ip_conntrack_expect_proto {
/* insert expect proto private data here */
};-- snip --
Acutally, rtsp/mms/h323 all failed on this. If I edit ip_conntrack.h by hand and fix the insertion marker, then the pom-ng can be applied but can't be compiled.
Here it is 23:30, so I say 'tomorrow' means I want to get a break now :)
Quoted 11 lines · Max Kellermann
Quoted 2 lines · Wang Jian
I tried it once with 2.6.11 and 2.6.11.6, both failed. But I will try it again tomorrow.
What failed exactly? Message? Reject file?
I guess changing the "time" parameter (= tomorrow) won't help in this case ;)
Max
Signature · 1 line
lark
Quoted 3 lines
Do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] y
unable to find ladd slot in src/tmp/pom-10691/include/linux/netfilter_ipv4/ip_conntrack.h(./h323-conntrack-nat/linux-2.6.11/./include/linux/netfilter_ipv4/ip_conntrack.h.ladd_3)
ah damn, that file is still in the pom-ng svn repository. It is obsolete and was deleted by a patch long ago, but that was forgotten.
Delete the file ip_conntrack.h.ladd_3 from your working copy, and it should finally work..
Max
Hi Max Kellermann,
Then perhaps this applies to all three of rtsp, h323 and mms?
Quoted 12 lines · Max Kellermann
Quoted 3 lines
Do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] y
unable to find ladd slot in src/tmp/pom-10691/include/linux/netfilter_ipv4/ip_conntrack.h(./h323-conntrack-nat/linux-2.6.11/./include/linux/netfilter_ipv4/ip_conntrack.h.ladd_3)ah damn, that file is still in the pom-ng svn repository. It is obsolete and was deleted by a patch long ago, but that was forgotten.
Delete the file ip_conntrack.h.ladd_3 from your working copy, and it should finally work..
Max
Signature · 1 line
lark
Quoted 10 lines · Max Kellermann
On 2005/04/04 16:01, Wang Jian <[email protected]> wrote:
[...]Quoted 7 lines
I want to make it works under 2.6.11 or 2.6.12. I really need your help to finish it in time.
I will spend a day (ideally) to look into the new conntrack infrastructure, and then I will spend time on every conntrack involved. If the old code works, I think it is not very hard to port them to new infrastructure. provided that new infrastruture is stable and good.
Quoted 5 lines
I already ported h323-conntrack-nat to 2.6.11, but my port is hidden in an obsolete branch in the pom-ng svn repository. Please grab my patch from my home page:
hm, seems we now have your and my (unfinished) port. I should have
read netfilter-devel more often, it seems.
I've now merged your code in svn trunk, please verify if everything works allright.
Signature · 5 lines
- Harald Welte <[email protected]> http://netfilter.org/ ============================================================================ "Fragmentation is like classful addressing -- an interesting early architectural error that shows how much experimentation was going on while IP was being designed." -- Paul Vixie
Quoted 2 lines · Harald Welte
hm, seems we now have your and my (unfinished) port. I should have read netfilter-devel more often, it seems.
Damn.. I'll Cc you from now on. I was unsure who of you guys was feeling responsible for applying my patches.
Quoted 2 lines
I've now merged your code in svn trunk, please verify if everything works allright.
Looks good, the code is identical to my local darcs tree (as far as I've submitted it already).
Max
Quoted 6 lines · Max Kellermann
Quoted 2 lines · Harald Welte
hm, seems we now have your and my (unfinished) port. I should have read netfilter-devel more often, it seems.
Damn.. I'll Cc you from now on. I was unsure who of you guys was feeling responsible for applying my patches.
well, it's always the one who tends to have more time at the given moment... which tends to change quite often.
netfilter-devel is the right place, but at the moment we all seem a bit busy with catching up, sorry. That's why I'm asking for the private cc.
Thanks.
Signature · 5 lines
- Harald Welte <[email protected]> http://netfilter.org/ ============================================================================ "Fragmentation is like classful addressing -- an interesting early architectural error that shows how much experimentation was going on while IP was being designed." -- Paul Vixie