* [patch] Re: SIP/RTP support coming?
2005-04-15 15:48 ` Harald Welte
@ 2005-04-15 22:46 ` Christian Hentschel
2005-04-15 22:54 ` Christian Hentschel
1 sibling, 0 replies; 9+ messages in thread
From: Christian Hentschel @ 2005-04-15 22:46 UTC (permalink / raw)
To: Harald Welte; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 926 bytes --]
Ok, here goes 2.6.11 patch.
I'm still working on nat SIP/SDP content mangling. But u should try this
patch meanwhile. It'd be great some help with it.
Let me know later.
Herald? Would it be possible to add it to pom if this works realiable?
On Fri, 2005-04-15 at 17:48 +0200, Harald Welte wrote:
> On Fri, Apr 15, 2005 at 09:44:03AM +0100, Steve Davies wrote:
> > Christian,
> >
> > Sorry about taking so long to get back to you - I have been using your
> > SIP conntrack helper for a little while now, and it seems to work very
> > well for me, also with kernel 2.6.10.
> >
> > Many thanks for providing it.
> >
> > One small problem I do have is the netfilter API change in kernel
> > 2.6.11 - Is this change documented anywhere? Is there a
> > porting/updating guide anywhere?
>
> unfortunately not. I suggest looking at a diff between 2.6.10 and
> 2.6.11 version of a helper (e.g. within patch-o-matic).
>
--
[-- Attachment #2: sip_conntrack.patch --]
[-- Type: text/x-patch, Size: 11151 bytes --]
Index: sip-conntrack-nat/include/linux/netfilter_ipv4/ip_conntrack_sip.h
===================================================================
--- sip-conntrack-nat/include/linux/netfilter_ipv4/ip_conntrack_sip.h (revision 0)
+++ sip-conntrack-nat/include/linux/netfilter_ipv4/ip_conntrack_sip.h (revision 0)
@@ -0,0 +1,24 @@
+#ifndef __IP_CONNTRACK_SIP_H__
+#define __IP_CONNTRACK_SIP_H__
+/* SIP tracking. */
+
+#ifdef __KERNEL__
+
+#define SIP_PORT 5060
+
+#endif /* __KERNEL__ */
+
+/* This structure exists only once per master */
+struct ip_ct_sip_master {
+ int dummy;
+};
+
+struct ip_conntrack_expect;
+
+/* For NAT to hook in when we find a packet which describes what other
+ * connection we should expect. */
+extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct ip_conntrack_expect *exp);
+
+#endif /* __IP_CONNTRACK_SIP_H__ */
Index: sip-conntrack-nat/net/ipv4/netfilter/Makefile.ladd
===================================================================
--- sip-conntrack-nat/net/ipv4/netfilter/Makefile.ladd (revision 0)
+++ sip-conntrack-nat/net/ipv4/netfilter/Makefile.ladd (revision 0)
@@ -0,0 +1,6 @@
+obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
+
+# SIP support
+obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
+obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
+
Index: sip-conntrack-nat/net/ipv4/netfilter/ip_conntrack_sip.c
===================================================================
--- sip-conntrack-nat/net/ipv4/netfilter/ip_conntrack_sip.c (revision 0)
+++ sip-conntrack-nat/net/ipv4/netfilter/ip_conntrack_sip.c (revision 0)
@@ -0,0 +1,269 @@
+/* SIP extension for IP connection tracking.
+ *
+ * (C) 2005 Christian Hentschel
+ * based on RR's ip_conntrack_ftp.c and other modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <linux/ctype.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+
+#include <linux/netfilter_ipv4/lockhelp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+//FIXME
+#include "ip_conntrack_sip.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com>");
+MODULE_DESCRIPTION("SIP connection tracking helper");
+
+/* This is slow, but it's simple. --RR */
+static char sip_buffer[65536];
+
+static DECLARE_LOCK(sipbf_lock);
+
+struct module *ip_conntrack_sip = THIS_MODULE;
+
+#define MAX_PORTS 8
+static int ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, int, &ports_c, 0400);
+MODULE_PARM_DESC(ports, " port numbers of sip servers");
+
+unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
+
+
+//#if 0
+#define DEBUGP printk
+//#else
+//#define DEBUGP(format, args...)
+//#endif
+
+static int rtp_expectfn(struct ip_conntrack *new)
+{
+ DEBUGP("ct_sip: Got expected RTP\n");
+
+ return 0;
+}
+
+static unsigned int skip_atoi(const char **str)
+{
+ unsigned int result = 0;
+
+ while (isdigit(**str))
+ result = result*10 + *((*str)++) - '0';
+
+ return result;
+}
+
+/*
+ * Simple IPaddr parser..
+ */
+static int has_ip(const char **str, uint32_t *ipaddr)
+{
+ int i, digit;
+ uint32_t val;
+
+ for (i = 0, *ipaddr = 0; i < 4; i++) {
+ digit = 0;
+ if (!isdigit(**str))
+ break;
+ if ((val = skip_atoi(str)) > 0xFF)
+ return -1;
+
+ ((uint8_t *)ipaddr)[i] = val;
+ digit = 1;
+
+ if (*(*str) != '.')
+ break;
+ (*str)++;
+ }
+ if (!digit)
+ return -1;
+
+ return 0;
+}
+
+static int get_rtpaddr(const char *data, uint32_t *ipaddr, uint16_t *port)
+{
+ const char *aux, *dptr;
+
+ dptr = strstr(data, "c=IN IP4 ");
+ if (!dptr) {
+ DEBUGP("'c=IN IP4 ' not found\n");
+ return -1;
+ }
+ dptr += 9;
+
+ /* Get ipaddr */
+ aux = dptr;
+ if (has_ip(&dptr, ipaddr) < 0) {
+ DEBUGP("has_ip() failed\n");
+ return -1;
+ }
+
+ dptr = strstr(data, "m=audio ");
+ if (!dptr) {
+ DEBUGP("'m=audio ' not found\n");
+ return -1;
+ }
+
+ dptr += 8;
+ aux = dptr;
+
+ *port = skip_atoi(&dptr);
+
+ if (*port < 1024)
+ return -1;
+
+ return 0;
+}
+
+static int set_expected_rtp(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo, u_int32_t ipaddr, u_int16_t port)
+{
+ struct ip_conntrack_expect *exp;
+
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL)
+ return NF_DROP;
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, { 0 } },
+ { ipaddr, { .udp = { htons(port) } }, IPPROTO_UDP }});
+
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0xFFFFFFFF, { 0 } },
+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+ exp->expectfn = NULL; //rtp_expectfn;
+ exp->master = ct;
+
+ DEBUGP("expect: ");
+ DUMP_TUPLE(&exp->tuple);
+ DUMP_TUPLE(&exp->mask);
+
+ if (ip_nat_sip_hook)
+ return ip_nat_sip_hook(pskb, ctinfo, exp);
+ else if (ip_conntrack_expect_related(exp) != 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
+
+static int sip_help(struct sk_buff **pskb,
+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+{
+ unsigned int dataoff, datalen;
+ char *dptr;
+
+ int ret = NF_ACCEPT;
+
+ uint32_t ipaddr = 0;
+ uint16_t port;
+
+ if ((ctinfo) >= IP_CT_IS_REPLY)
+ return NF_ACCEPT;
+
+ /* No Data ? */
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+ if (dataoff >= (*pskb)->len) {
+ DEBUGP("skb->len = %u\n", (*pskb)->len);
+ return NF_ACCEPT;
+ }
+
+ datalen = (*pskb)->len - dataoff;
+
+ LOCK_BH(&sipbf_lock);
+
+ dptr = skb_header_pointer(*pskb, dataoff, datalen, sip_buffer);
+ BUG_ON(dptr == NULL);
+
+ DEBUGP("datalen %u\n", datalen);
+
+ /* RTP info only in SDP interestin packets */
+ if (memcmp(dptr, "INVITE", 6) != 0 && memcmp(dptr, "SIP/2.0 200", 11) != 0) {
+ DEBUGP("Not interesting pkt.\n");
+ goto out;
+ }
+
+ *(dptr + datalen) = '\0';
+
+ if (get_rtpaddr(dptr, &ipaddr, &port) < 0)
+ goto out;
+
+ ret = set_expected_rtp(pskb, ct, ctinfo, ipaddr, port);
+
+out: UNLOCK_BH(&sipbf_lock);
+ return ret;
+}
+
+static struct ip_conntrack_helper sip[MAX_PORTS];
+static char sip_names[MAX_PORTS][10];
+
+static void fini(void)
+{
+ int i = 0;
+ for (; i < ports_c; i++) {
+ DEBUGP("unregistering helper for port %d\n", ports[i]);
+ ip_conntrack_helper_unregister(&sip[i]);
+ }
+}
+
+static int __init init(void)
+{
+ int i, ret;
+ char *tmpname;
+
+ if (ports_c == 0)
+ ports[ports_c++] = SIP_PORT;
+
+ for (i = 0; i < ports_c; i++) {
+ /* Create helper structure */
+ memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
+
+ sip[i].tuple.dst.protonum = IPPROTO_UDP;
+ sip[i].tuple.src.u.udp.port = htons(ports[i]);
+ sip[i].mask.src.u.udp.port = 0xFFFF;
+ sip[i].mask.dst.protonum = 0xFF;
+ sip[i].max_expected = 2;
+ sip[i].timeout = 3 * 60; /* 3 minutes */
+ sip[i].me = THIS_MODULE;
+ sip[i].help = sip_help;
+
+ tmpname = &sip_names[i][0];
+ if (ports[i] == SIP_PORT)
+ sprintf(tmpname, "sip");
+ else
+ sprintf(tmpname, "sip-%d", i);
+ sip[i].name = tmpname;
+
+ DEBUGP("port #%d: %d\n", i, ports[i]);
+
+ ret=ip_conntrack_helper_register(&sip[i]);
+ if (ret) {
+ printk("ERROR registering helper for port %d\n",
+ ports[i]);
+ fini();
+ return(ret);
+ }
+ }
+ return(0);
+}
+
+module_init(init);
+module_exit(fini);
Index: sip-conntrack-nat/net/ipv4/netfilter/ip_nat_sip.c
===================================================================
--- sip-conntrack-nat/net/ipv4/netfilter/ip_nat_sip.c (revision 0)
+++ sip-conntrack-nat/net/ipv4/netfilter/ip_nat_sip.c (revision 0)
@@ -0,0 +1,97 @@
+/* SIP extension for SIP NAT alteration.
+ *
+ * (C) 2005 Christian Hentschel
+ * based on RR's ip_nat_ftp.c and other modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/moduleparam.h>
+#include <net/udp.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+//FIXME
+#include "ip_conntrack_sip.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com>");
+MODULE_DESCRIPTION("SIP NAT helper");
+
+//#if 0
+#define DEBUGP printk
+//#else
+//#define DEBUGP(format, args...)
+//#endif
+
+
+/* So, this packet has hit the connection tracking matching code.
+ Mangle it, and change the expectation to match the new version. */
+static unsigned int ip_nat_sip(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo, struct ip_conntrack_expect *exp)
+{
+ u_int32_t newip;
+ u_int16_t port;
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack *ct = exp->master;
+
+ DEBUGP("SIP_NAT: ");
+
+ /* Connection will come from wherever this packet goes, hence !dir */
+ newip = ct->tuplehash[!dir].tuple.dst.ip;
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->dir = !dir;
+
+ /* When you see the packet, we need to NAT it the same as the
+ * this one. */
+ exp->expectfn = ip_nat_follow_master;
+
+ /* Try to get same port: if not, try to change it. */
+ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+ exp->tuple.dst.u.tcp.port = htons(port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (port == 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ }
+
+/*
+ * Hard stuff, mangle data inside the packet..
+
+ if () {
+ ip_conntrack_unexpect_related(exp);
+ return NF_DROP;
+ }
+*/
+ DEBUGP("new addr: %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
+
+ return NF_ACCEPT;
+}
+
+static void __exit fini(void)
+{
+ ip_nat_sip_hook = NULL;
+ /* Make sure noone calls it, meanwhile. */
+ synchronize_net();
+}
+
+static int __init init(void)
+{
+ BUG_ON(ip_nat_sip_hook);
+ ip_nat_sip_hook = ip_nat_sip;
+ return 0;
+}
+
+module_init(init);
+module_exit(fini);
Index: sip-conntrack-nat/info
===================================================================
--- sip-conntrack-nat/info (revision 0)
+++ sip-conntrack-nat/info (revision 0)
@@ -0,0 +1,5 @@
+Title: h323 connection tracking and NAT helper
+Author: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>, Max Kellermann <max@duempel.org>
+Status: Alpha
+Repository: extra
+Requires: linux-2.6 >= 2.6.11
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: SIP/RTP support coming?
2005-04-15 15:48 ` Harald Welte
2005-04-15 22:46 ` [patch] " Christian Hentschel
@ 2005-04-15 22:54 ` Christian Hentschel
1 sibling, 0 replies; 9+ messages in thread
From: Christian Hentschel @ 2005-04-15 22:54 UTC (permalink / raw)
To: Harald Welte; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 733 bytes --]
Ups, sorry here goes again with "info" file fixed.
On Fri, 2005-04-15 at 17:48 +0200, Harald Welte wrote:
> On Fri, Apr 15, 2005 at 09:44:03AM +0100, Steve Davies wrote:
> > Christian,
> >
> > Sorry about taking so long to get back to you - I have been using your
> > SIP conntrack helper for a little while now, and it seems to work very
> > well for me, also with kernel 2.6.10.
> >
> > Many thanks for providing it.
> >
> > One small problem I do have is the netfilter API change in kernel
> > 2.6.11 - Is this change documented anywhere? Is there a
> > porting/updating guide anywhere?
>
> unfortunately not. I suggest looking at a diff between 2.6.10 and
> 2.6.11 version of a helper (e.g. within patch-o-matic).
>
--
[-- Attachment #2: sip_conntrack.patch --]
[-- Type: text/x-patch, Size: 11118 bytes --]
Index: sip-conntrack-nat/include/linux/netfilter_ipv4/ip_conntrack_sip.h
===================================================================
--- sip-conntrack-nat/include/linux/netfilter_ipv4/ip_conntrack_sip.h (revision 0)
+++ sip-conntrack-nat/include/linux/netfilter_ipv4/ip_conntrack_sip.h (revision 0)
@@ -0,0 +1,24 @@
+#ifndef __IP_CONNTRACK_SIP_H__
+#define __IP_CONNTRACK_SIP_H__
+/* SIP tracking. */
+
+#ifdef __KERNEL__
+
+#define SIP_PORT 5060
+
+#endif /* __KERNEL__ */
+
+/* This structure exists only once per master */
+struct ip_ct_sip_master {
+ int dummy;
+};
+
+struct ip_conntrack_expect;
+
+/* For NAT to hook in when we find a packet which describes what other
+ * connection we should expect. */
+extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct ip_conntrack_expect *exp);
+
+#endif /* __IP_CONNTRACK_SIP_H__ */
Index: sip-conntrack-nat/net/ipv4/netfilter/Makefile.ladd
===================================================================
--- sip-conntrack-nat/net/ipv4/netfilter/Makefile.ladd (revision 0)
+++ sip-conntrack-nat/net/ipv4/netfilter/Makefile.ladd (revision 0)
@@ -0,0 +1,6 @@
+obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
+
+# SIP support
+obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
+obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
+
Index: sip-conntrack-nat/net/ipv4/netfilter/ip_conntrack_sip.c
===================================================================
--- sip-conntrack-nat/net/ipv4/netfilter/ip_conntrack_sip.c (revision 0)
+++ sip-conntrack-nat/net/ipv4/netfilter/ip_conntrack_sip.c (revision 0)
@@ -0,0 +1,269 @@
+/* SIP extension for IP connection tracking.
+ *
+ * (C) 2005 Christian Hentschel
+ * based on RR's ip_conntrack_ftp.c and other modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <linux/ctype.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+
+#include <linux/netfilter_ipv4/lockhelp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+//FIXME
+#include "ip_conntrack_sip.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com>");
+MODULE_DESCRIPTION("SIP connection tracking helper");
+
+/* This is slow, but it's simple. --RR */
+static char sip_buffer[65536];
+
+static DECLARE_LOCK(sipbf_lock);
+
+struct module *ip_conntrack_sip = THIS_MODULE;
+
+#define MAX_PORTS 8
+static int ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, int, &ports_c, 0400);
+MODULE_PARM_DESC(ports, " port numbers of sip servers");
+
+unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
+
+
+//#if 0
+#define DEBUGP printk
+//#else
+//#define DEBUGP(format, args...)
+//#endif
+
+static int rtp_expectfn(struct ip_conntrack *new)
+{
+ DEBUGP("ct_sip: Got expected RTP\n");
+
+ return 0;
+}
+
+static unsigned int skip_atoi(const char **str)
+{
+ unsigned int result = 0;
+
+ while (isdigit(**str))
+ result = result*10 + *((*str)++) - '0';
+
+ return result;
+}
+
+/*
+ * Simple IPaddr parser..
+ */
+static int has_ip(const char **str, uint32_t *ipaddr)
+{
+ int i, digit;
+ uint32_t val;
+
+ for (i = 0, *ipaddr = 0; i < 4; i++) {
+ digit = 0;
+ if (!isdigit(**str))
+ break;
+ if ((val = skip_atoi(str)) > 0xFF)
+ return -1;
+
+ ((uint8_t *)ipaddr)[i] = val;
+ digit = 1;
+
+ if (*(*str) != '.')
+ break;
+ (*str)++;
+ }
+ if (!digit)
+ return -1;
+
+ return 0;
+}
+
+static int get_rtpaddr(const char *data, uint32_t *ipaddr, uint16_t *port)
+{
+ const char *aux, *dptr;
+
+ dptr = strstr(data, "c=IN IP4 ");
+ if (!dptr) {
+ DEBUGP("'c=IN IP4 ' not found\n");
+ return -1;
+ }
+ dptr += 9;
+
+ /* Get ipaddr */
+ aux = dptr;
+ if (has_ip(&dptr, ipaddr) < 0) {
+ DEBUGP("has_ip() failed\n");
+ return -1;
+ }
+
+ dptr = strstr(data, "m=audio ");
+ if (!dptr) {
+ DEBUGP("'m=audio ' not found\n");
+ return -1;
+ }
+
+ dptr += 8;
+ aux = dptr;
+
+ *port = skip_atoi(&dptr);
+
+ if (*port < 1024)
+ return -1;
+
+ return 0;
+}
+
+static int set_expected_rtp(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo, u_int32_t ipaddr, u_int16_t port)
+{
+ struct ip_conntrack_expect *exp;
+
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL)
+ return NF_DROP;
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, { 0 } },
+ { ipaddr, { .udp = { htons(port) } }, IPPROTO_UDP }});
+
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0xFFFFFFFF, { 0 } },
+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+ exp->expectfn = NULL; //rtp_expectfn;
+ exp->master = ct;
+
+ DEBUGP("expect: ");
+ DUMP_TUPLE(&exp->tuple);
+ DUMP_TUPLE(&exp->mask);
+
+ if (ip_nat_sip_hook)
+ return ip_nat_sip_hook(pskb, ctinfo, exp);
+ else if (ip_conntrack_expect_related(exp) != 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
+
+static int sip_help(struct sk_buff **pskb,
+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+{
+ unsigned int dataoff, datalen;
+ char *dptr;
+
+ int ret = NF_ACCEPT;
+
+ uint32_t ipaddr = 0;
+ uint16_t port;
+
+ if ((ctinfo) >= IP_CT_IS_REPLY)
+ return NF_ACCEPT;
+
+ /* No Data ? */
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+ if (dataoff >= (*pskb)->len) {
+ DEBUGP("skb->len = %u\n", (*pskb)->len);
+ return NF_ACCEPT;
+ }
+
+ datalen = (*pskb)->len - dataoff;
+
+ LOCK_BH(&sipbf_lock);
+
+ dptr = skb_header_pointer(*pskb, dataoff, datalen, sip_buffer);
+ BUG_ON(dptr == NULL);
+
+ DEBUGP("datalen %u\n", datalen);
+
+ /* RTP info only in SDP interestin packets */
+ if (memcmp(dptr, "INVITE", 6) != 0 && memcmp(dptr, "SIP/2.0 200", 11) != 0) {
+ DEBUGP("Not interesting pkt.\n");
+ goto out;
+ }
+
+ *(dptr + datalen) = '\0';
+
+ if (get_rtpaddr(dptr, &ipaddr, &port) < 0)
+ goto out;
+
+ ret = set_expected_rtp(pskb, ct, ctinfo, ipaddr, port);
+
+out: UNLOCK_BH(&sipbf_lock);
+ return ret;
+}
+
+static struct ip_conntrack_helper sip[MAX_PORTS];
+static char sip_names[MAX_PORTS][10];
+
+static void fini(void)
+{
+ int i = 0;
+ for (; i < ports_c; i++) {
+ DEBUGP("unregistering helper for port %d\n", ports[i]);
+ ip_conntrack_helper_unregister(&sip[i]);
+ }
+}
+
+static int __init init(void)
+{
+ int i, ret;
+ char *tmpname;
+
+ if (ports_c == 0)
+ ports[ports_c++] = SIP_PORT;
+
+ for (i = 0; i < ports_c; i++) {
+ /* Create helper structure */
+ memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
+
+ sip[i].tuple.dst.protonum = IPPROTO_UDP;
+ sip[i].tuple.src.u.udp.port = htons(ports[i]);
+ sip[i].mask.src.u.udp.port = 0xFFFF;
+ sip[i].mask.dst.protonum = 0xFF;
+ sip[i].max_expected = 2;
+ sip[i].timeout = 3 * 60; /* 3 minutes */
+ sip[i].me = THIS_MODULE;
+ sip[i].help = sip_help;
+
+ tmpname = &sip_names[i][0];
+ if (ports[i] == SIP_PORT)
+ sprintf(tmpname, "sip");
+ else
+ sprintf(tmpname, "sip-%d", i);
+ sip[i].name = tmpname;
+
+ DEBUGP("port #%d: %d\n", i, ports[i]);
+
+ ret=ip_conntrack_helper_register(&sip[i]);
+ if (ret) {
+ printk("ERROR registering helper for port %d\n",
+ ports[i]);
+ fini();
+ return(ret);
+ }
+ }
+ return(0);
+}
+
+module_init(init);
+module_exit(fini);
Index: sip-conntrack-nat/net/ipv4/netfilter/ip_nat_sip.c
===================================================================
--- sip-conntrack-nat/net/ipv4/netfilter/ip_nat_sip.c (revision 0)
+++ sip-conntrack-nat/net/ipv4/netfilter/ip_nat_sip.c (revision 0)
@@ -0,0 +1,97 @@
+/* SIP extension for SIP NAT alteration.
+ *
+ * (C) 2005 Christian Hentschel
+ * based on RR's ip_nat_ftp.c and other modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/moduleparam.h>
+#include <net/udp.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+//FIXME
+#include "ip_conntrack_sip.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com>");
+MODULE_DESCRIPTION("SIP NAT helper");
+
+//#if 0
+#define DEBUGP printk
+//#else
+//#define DEBUGP(format, args...)
+//#endif
+
+
+/* So, this packet has hit the connection tracking matching code.
+ Mangle it, and change the expectation to match the new version. */
+static unsigned int ip_nat_sip(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo, struct ip_conntrack_expect *exp)
+{
+ u_int32_t newip;
+ u_int16_t port;
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack *ct = exp->master;
+
+ DEBUGP("SIP_NAT: ");
+
+ /* Connection will come from wherever this packet goes, hence !dir */
+ newip = ct->tuplehash[!dir].tuple.dst.ip;
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->dir = !dir;
+
+ /* When you see the packet, we need to NAT it the same as the
+ * this one. */
+ exp->expectfn = ip_nat_follow_master;
+
+ /* Try to get same port: if not, try to change it. */
+ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+ exp->tuple.dst.u.tcp.port = htons(port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (port == 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ }
+
+/*
+ * Hard stuff, mangle data inside the packet..
+
+ if () {
+ ip_conntrack_unexpect_related(exp);
+ return NF_DROP;
+ }
+*/
+ DEBUGP("new addr: %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
+
+ return NF_ACCEPT;
+}
+
+static void __exit fini(void)
+{
+ ip_nat_sip_hook = NULL;
+ /* Make sure noone calls it, meanwhile. */
+ synchronize_net();
+}
+
+static int __init init(void)
+{
+ BUG_ON(ip_nat_sip_hook);
+ ip_nat_sip_hook = ip_nat_sip;
+ return 0;
+}
+
+module_init(init);
+module_exit(fini);
Index: sip-conntrack-nat/info
===================================================================
--- sip-conntrack-nat/info (revision 0)
+++ sip-conntrack-nat/info (revision 0)
@@ -0,0 +1,5 @@
+Title: SIP connection tracking and NAT helper
+Author: Christian Hentschel <chentschel@arnet.com.ar>
+Status: Alpha
+Repository: extra
+Requires: linux-2.6 >= 2.6.11
^ permalink raw reply [flat|nested] 9+ messages in thread