diff options
Diffstat (limited to 'target/linux/generic-2.4/patches/613-netfilter_nat_sip.patch')
-rw-r--r-- | target/linux/generic-2.4/patches/613-netfilter_nat_sip.patch | 1254 |
1 files changed, 0 insertions, 1254 deletions
diff --git a/target/linux/generic-2.4/patches/613-netfilter_nat_sip.patch b/target/linux/generic-2.4/patches/613-netfilter_nat_sip.patch deleted file mode 100644 index 3ccbe94d0..000000000 --- a/target/linux/generic-2.4/patches/613-netfilter_nat_sip.patch +++ /dev/null @@ -1,1254 +0,0 @@ -diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.new/net/ipv4/netfilter/Config.in ---- linux-2.4.32/net/ipv4/netfilter/Config.in 2006-02-04 19:16:25.000000000 +0100 -+++ linux-2.4.32.new/net/ipv4/netfilter/Config.in 2006-02-04 19:00:13.000000000 +0100 -@@ -15,6 +15,7 @@ - dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES - dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK - dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE -+ dep_tristate ' SIP protocol support' CONFIG_IP_NF_SIP $CONFIG_IP_NF_CONNTRACK - fi - - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -@@ -103,6 +104,13 @@ - define_tristate CONFIG_IP_NF_NAT_PROTO_GRE $CONFIG_IP_NF_NAT - fi - fi -+ if [ "$CONFIG_IP_NF_SIP" = "m" ]; then -+ define_tristate CONFIG_IP_NF_NAT_SIP m -+ else -+ if [ "$CONFIG_IP_NF_SIP" = "y" ]; then -+ define_tristate CONFIG_IP_NF_NAT_SIP $CONFIG_IP_NF_NAT -+ fi -+ fi - if [ "$CONFIG_IP_NF_AMANDA" = "m" ]; then - define_tristate CONFIG_IP_NF_NAT_AMANDA m - else -diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_sip.c linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_sip.c ---- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_sip.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_sip.c 2006-02-04 19:06:01.000000000 +0100 -@@ -0,0 +1,312 @@ -+/* -+ * SIP extension for IP connection tracking. -+ * -+ * Copyright (C) 2004, CyberTAN Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/netfilter.h> -+#include <linux/ip.h> -+#include <linux/ctype.h> -+#include <net/checksum.h> -+#include <net/tcp.h> -+ -+#include <linux/netfilter_ipv4/lockhelp.h> -+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> -+#include <linux/netfilter_ipv4/ip_conntrack_sip.h> -+#include <linux/netfilter_ipv4/ip_conntrack_core.h> -+ -+DECLARE_LOCK(ip_sip_lock); -+ -+struct module *ip_conntrack_sip = THIS_MODULE; -+ -+#define MAX_PORTS 8 -+static int ports[MAX_PORTS]; -+static int ports_c; -+#ifdef MODULE_PARM -+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); -+#endif -+ -+#if 0 -+ #define DEBUGP printk -+#else -+ #define DEBUGP(format, args...) -+#endif -+ -+#define RTCP_SUPPORT -+ -+static int set_expected_rtp(struct ip_conntrack *ct, u_int32_t dstip, -+ u_int16_t dstport, unsigned int conntype) -+{ -+ struct ip_conntrack_expect expect, *exp = &expect; -+ struct ip_ct_sip_expect *exp_sip_info = &exp->help.exp_sip_info; -+ int ret = 0; -+ -+ memset(&expect, 0, sizeof(expect)); -+ LOCK_BH(&ip_sip_lock); -+ -+ DEBUGP("conntrack_sip: %s: [%s]: DST=%u.%u.%u.%u:%u\n", __FUNCTION__, -+ conntype == CONN_RTP ? "RTP" : "RTCP", NIPQUAD(dstip), dstport); -+ -+ /* exp_sip_info */ -+ exp_sip_info->port = dstport; -+ exp_sip_info->type = conntype; -+ exp_sip_info->nated = 0; -+ -+ /* new expectation */ -+ exp->tuple = ((struct ip_conntrack_tuple) -+ { { 0, { 0 } }, -+ { dstip, { htons(dstport) }, IPPROTO_UDP }}); -+ exp->mask = ((struct ip_conntrack_tuple) -+ { { 0, { 0 } }, -+ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }}); -+ exp->expectfn = NULL; -+ -+ if ((ret=ip_conntrack_expect_related(ct, exp)) != 0) { -+ DEBUGP("Can't add new expectation. \n"); -+ } -+ -+ UNLOCK_BH(&ip_sip_lock); -+ -+ return ret; -+} -+ -+/* -+static int unset_expected_rtp(struct ip_conntrack *ct, u_int32_t dstip, u_int16_t dstport) -+{ -+ struct ip_conntrack_expect *exp; -+ const struct ip_conntrack_tuple tuple = { { 0, { 0 } }, -+ { dstip, { htons(dstport) }, IPPROTO_UDP }}; -+ -+ LOCK_BH(&ip_sip_lock); -+ -+ exp = ip_conntrack_expect_find_get(&tuple); -+ if (exp) { -+ DEBUGP("Find the expectation %p, then delete it.\n", exp); -+ ip_conntrack_unexpect_related(exp); -+ } -+ -+ UNLOCK_BH(&ip_sip_lock); -+ -+ return 0; -+}*/ -+ -+/* return: -+ * 0 : Not found -+ * 1 : Found domain name -+ * 2 : Found dotted quads -+ */ -+int find_sdp_rtp_addr(const char *data, size_t dlen, -+ unsigned int *numoff, unsigned int *numlen, u_int32_t *addr) -+{ -+ char *st, *p = (char *)data; -+ const char *limit = data + dlen; -+ unsigned char p1, p2, p3, p4; -+ -+ while (p < limit) { -+ /* find 'c=' line */ -+ if (strncmp(p, "\nc=",3) && strncmp(p, "\rc=",3)) { -+ p++; -+ continue; -+ } -+ p += 3; -+ -+ if (strncmp(p, "IN IP4 ",7)) -+ continue; -+ p += 7; -+ -+ /* IP address */ -+ st = p; -+ -+ /* FQDNs or dotted quads */ -+ while (isalpha(*p) || isdigit(*p) || (*p=='.') || (*p=='-')) { -+ p++; -+ if (p == limit) -+ return 0; -+ } -+ -+ *numoff = st - data; -+ *numlen = p - st; -+ -+ /* Convert the IP address */ -+ p1 = simple_strtoul(st, &st ,10); -+ if (*st != '.') -+ return 1; -+ p2 = simple_strtoul(st+1, &st, 10); -+ if (*st != '.') -+ return 1; -+ p3 = simple_strtoul(st+1, &st, 10); -+ if (*st != '.') -+ return 1; -+ p4 = simple_strtoul(st+1, &st, 10); -+ -+ *addr = (p1<<24) | (p2<<16) | (p3<<8) | p4; -+ -+ return 2; -+ } -+ -+ return 0; -+} -+ -+u_int16_t find_sdp_audio_port(const char *data, size_t dlen, -+ unsigned int *numoff, unsigned int *numlen) -+{ -+ char *st, *p = (char *)data; -+ const char *limit = data + dlen; -+ u_int16_t port = 0; -+ -+ while (p < limit) { -+ /* find 'm=' */ -+ if (strncmp(p, "\nm=", 3) && strncmp(p, "\rm=", 3)) { -+ p++; -+ continue; -+ } -+ p += 3; -+ -+ /* audio stream */ -+ if (strncmp(p ,"audio ",6)) -+ continue; -+ p += 6; -+ -+ st = p; -+ port = simple_strtoul(p, &p, 10); -+ -+ *numoff = st - data; -+ *numlen = p - st; -+ -+ return port; -+ } -+ -+ return 0; -+} -+ -+static int help(const struct iphdr *iph, size_t len, -+ struct ip_conntrack *ct, -+ enum ip_conntrack_info ctinfo) -+{ -+ int dir = CTINFO2DIR(ctinfo); -+ unsigned int matchlen, matchoff; -+ -+ u_int32_t ipaddr=0; -+ u_int16_t port = 0; -+ -+ int found = 0; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ unsigned int udplen = len - iph->ihl * 4; -+ unsigned int datalen = udplen - 8; -+ struct ip_ct_sip_master *ct_sip_info = &ct->help.ct_sip_info; -+ -+ DEBUGP("\nconntrack_sip: help(): DIR=%d, conntrackinfo=%u\n", dir, ctinfo); -+ DEBUGP("conntrack_sip: %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", -+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip), -+ ntohs(ct->tuplehash[dir].tuple.src.u.udp.port), -+ NIPQUAD(ct->tuplehash[dir].tuple.dst.ip), -+ ntohs(ct->tuplehash[dir].tuple.dst.u.udp.port) ); -+ -+ /* Reset for a new incoming packet */ -+ ct_sip_info->mangled = 0; -+ -+ /* keep the connection alive */ -+ ip_ct_refresh_acct(ct, ctinfo, iph, (SIP_EXPIRES * HZ)); -+ -+ /* Don't need to set the expectation for upstream direction */ -+ if (dir == IP_CT_DIR_REPLY) -+ return NF_ACCEPT; -+ -+ /* Need to set the expected connection for further incoming RTP stream */ -+ if (strncmp(data, "INVITE", 6) != 0 && strncmp(data, "SIP/2.0 200", 11) != 0) { -+ DEBUGP("conntrack_sip: Not interesting packet.\n"); -+ return NF_ACCEPT; -+ } -+ -+ /* Find RTP address */ -+ found = find_sdp_rtp_addr(data, datalen, &matchoff, &matchlen, &ipaddr); -+ if (!found) -+ return NF_ACCEPT; -+ -+ DEBUGP("conntrack_sip: 'IN IP4' is %s.\n", (found == 1) ? "FQDNs" : "dotted quads"); -+ -+ /* If it's a null address, then the call is on hold */ -+ if (found == 2 && ipaddr == 0) { -+ DEBUGP("conntrack_sip: Null address is found.\n"); -+ return NF_ACCEPT; -+ } -+ -+ /* Find audio port, and we don't like the well-known ports, -+ * which is less than 1024 */ -+ port = find_sdp_audio_port(data, datalen, &matchoff, &matchlen); -+ if (port < 1024) -+ return NF_ACCEPT; -+ -+ DEBUGP("conntrack_sip: audio port=%d.\n", port); -+ -+ ipaddr = ct->tuplehash[dir].tuple.src.ip; -+ ct_sip_info->rtpport = port; -+ -+ /* RFC1889 - RTP uses an even port number and the corresponding RTCP -+ * stream uses the next higher (odd) port number. */ -+ if (set_expected_rtp(ct, ipaddr, port, CONN_RTP) == 0) { -+#ifdef RTCP_SUPPORT -+ set_expected_rtp(ct, ipaddr, port + 1, CONN_RTCP); -+#endif -+ } -+ -+ return NF_ACCEPT; -+} -+ -+static struct ip_conntrack_helper sip[MAX_PORTS]; -+ -+ -+/* Not __exit: called from init() */ -+static void fini(void) -+{ -+ int i; -+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { -+ DEBUGP("ip_ct_sip: unregistering helper for port %d\n", -+ ports[i]); -+ ip_conntrack_helper_unregister(&sip[i]); -+ } -+} -+ -+static int __init init(void) -+{ -+ int i, ret; -+ -+ if (ports[0] == 0) -+ ports[0] = SIP_PORT; -+ -+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { -+ memset(&sip[i], 0, sizeof(struct ip_conntrack_helper)); -+ sip[i].tuple.dst.u.udp.port = htons(ports[i]); -+ sip[i].tuple.dst.protonum = IPPROTO_UDP; -+ sip[i].mask.dst.u.udp.port = 0xF0FF; -+ sip[i].mask.dst.protonum = 0xFFFF; -+ sip[i].help = help; -+ sip[i].timeout = RTP_TIMEOUT; -+ DEBUGP("ip_ct_sip: registering helper for port %d\n", -+ ports[i]); -+ ret = ip_conntrack_helper_register(&sip[i]); -+ -+ if (ret) { -+ fini(); -+ return ret; -+ } -+ ports_c++; -+ } -+ return 0; -+} -+ -+ -+EXPORT_SYMBOL(ip_sip_lock); -+EXPORT_SYMBOL(ip_conntrack_sip); -+ -+module_init(init); -+module_exit(fini); -diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_sip.c linux-2.4.32.new/net/ipv4/netfilter/ip_nat_sip.c ---- linux-2.4.32/net/ipv4/netfilter/ip_nat_sip.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32.new/net/ipv4/netfilter/ip_nat_sip.c 2006-02-04 19:00:13.000000000 +0100 -@@ -0,0 +1,800 @@ -+/* -+ * SIP extension for TCP NAT alteration. -+ * -+ * Copyright (C) 2004, CyberTAN Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/netfilter_ipv4.h> -+#include <linux/ip.h> -+#include <linux/tcp.h> -+#include <linux/udp.h> -+#include <linux/ctype.h> -+#include <net/tcp.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_sip.h> -+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> -+ -+#if 0 -+ #define DEBUGP printk -+#else -+ #define DEBUGP(format, args...) -+#endif -+ -+#define MAX_PORTS 8 -+static int ports[MAX_PORTS]; -+static int ports_c = 0; -+ -+#ifdef MODULE_PARM -+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); -+#endif -+ -+DECLARE_LOCK_EXTERN(ip_sip_lock); -+ -+#define RTCP_SUPPORT -+ -+/* down(stream): caller -> callee -+ up(stream): caller <- callee */ -+ -+ -+/* Return 1 for match, 0 for accept, -1 for partial. */ -+static int find_pattern(const char *data, size_t dlen, -+ const char *pattern, size_t plen, -+ char skip, char term, -+ unsigned int *numoff, -+ unsigned int *numlen -+ ) -+{ -+ size_t i, j, k; -+ -+// DEBUGP("find_pattern `%s': dlen = %u\n", pattern, dlen); -+ if (dlen == 0) -+ return 0; -+ -+ if (dlen <= plen) { -+ /* Short packet: try for partial? */ -+ if (strnicmp(data, pattern, dlen) == 0) -+ return -1; -+ else return 0; -+ } -+ -+ for(i=0; i<= (dlen - plen); i++){ -+ if( memcmp(data + i, pattern, plen ) != 0 ) continue; -+ -+ /* patten match !! */ -+ *numoff=i + plen; -+ for (j=*numoff, k=0; data[j] != term; j++, k++) -+ if( j > dlen ) return -1 ; /* no terminal char */ -+ -+ *numlen = k; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static unsigned int -+sip_nat_expected(struct sk_buff **pskb, -+ unsigned int hooknum, -+ struct ip_conntrack *ct, -+ struct ip_nat_info *info) -+{ -+ struct ip_nat_multi_range mr; -+ u_int32_t newdstip, newsrcip, newip; -+ struct ip_ct_sip_expect *exp_sip_info; -+ struct ip_conntrack *master = master_ct(ct); -+ -+ IP_NF_ASSERT(info); -+ IP_NF_ASSERT(master); -+ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum)))); -+ -+ exp_sip_info = &ct->master->help.exp_sip_info; -+ -+ LOCK_BH(&ip_sip_lock); -+ -+ /* Outer machine IP */ -+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; -+ /* Client (virtual) IP under NAT */ -+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; -+ -+ UNLOCK_BH(&ip_sip_lock); -+ -+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) -+ newip = newsrcip; -+ else -+ newip = newdstip; -+ -+ DEBUGP("sip_nat_expected: IP to %u.%u.%u.%u:%u\n", NIPQUAD(newip), -+ htons(exp_sip_info->port)); -+ -+ mr.rangesize = 1; -+ /* We don't want to manip the per-protocol, just the IPs... */ -+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; -+ mr.range[0].min_ip = mr.range[0].max_ip = newip; -+ -+ /* ... unless we're doing a MANIP_DST, in which case, make -+ sure we map to the correct port */ -+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) { -+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; -+ mr.range[0].min = mr.range[0].max -+ = ((union ip_conntrack_manip_proto) -+ { htons(exp_sip_info->port) }); -+ } -+ -+ return ip_nat_setup_info(ct, &mr, hooknum); -+} -+ -+static int _find_sip_via_addrport(const char *data, size_t dlen, -+ unsigned int *numoff, unsigned int *numlen) -+{ -+ const char *addr, *p = data; -+ const char *limit = data + dlen; -+ -+ while (p < limit) { -+ /* Find the topmost via tag */ -+ if (strnicmp(p, "\nvia:",5) && strnicmp(p, "\nv:",3) && -+ strnicmp(p, "\rvia:",5) && strnicmp(p, "\rv:",3)) { -+ p++; -+ continue; -+ } -+ -+ /* Look for UDP */ -+ while (*p!='U' && *p!='u') { -+ if (p == limit) -+ return 0; -+ p++; -+ } -+ p+= 3; -+ -+ if (p >= limit) -+ return 0; -+ -+ /* Skip a space */ -+ while (*p == ' '){ -+ if (p == limit) -+ return 0; -+ p++; -+ } -+ -+ /* IP address */ -+ addr = p; -+ -+ /* FQDNs or dotted quads */ -+ while (isalpha(*p) || isdigit(*p) || (*p=='.') || (*p=='-')) { -+ p++; -+ if (p == limit) -+ return 0; -+ } -+ -+ /* If there is a port number, skip it */ -+ if (*p == ':') { -+ p++; -+ if (p == limit) -+ return 0; -+ -+ while (isdigit(*p)) { -+ p++; -+ if (p == limit) -+ return 0; -+ } -+ } -+ -+ *numoff = addr - data; -+ *numlen = p - addr; -+ -+ return 1; -+ } -+ -+ return 0; /* Not found */ -+} -+ -+static int _mangle_sip_via(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, -+ struct sk_buff **pskb, u_int32_t newip, u_int16_t newport, -+ unsigned int numoff, unsigned int numlen) -+{ -+ int buflen; -+ char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; -+ -+ sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(newip), newport); -+ buflen = strlen(buffer); -+ -+ MUST_BE_LOCKED(&ip_sip_lock); -+ -+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, numoff, -+ numlen, buffer, buflen) ) -+ return 0; -+ -+ DEBUGP("(SIP) Via is changed to %s.\n", buffer); -+ -+ return buflen - numlen; -+} -+ -+static int mangle_sip_via(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, -+ struct sk_buff **pskb, u_int32_t newip, u_int16_t newport) -+{ -+ struct iphdr *iph = (*pskb)->nh.iph; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ unsigned int udplen = ntohs(iph->tot_len) - (iph->ihl * 4); -+ unsigned int datalen = udplen - 8; -+ unsigned int matchoff, matchlen; -+ -+ /* Find the topmost via tag */ -+ _find_sip_via_addrport(data , datalen, &matchoff, &matchlen); -+ return _mangle_sip_via(ct, ctinfo, pskb, newip, newport, -+ matchoff, matchlen); -+} -+ -+static int mangle_sip_contact(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, -+ struct sk_buff **pskb, u_int32_t newip, u_int16_t newport) -+{ -+ struct iphdr *iph = (*pskb)->nh.iph; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ unsigned int udplen = ntohs(iph->tot_len) - (iph->ihl * 4); -+ unsigned int datalen = udplen - 8; -+ -+ int buflen, diff_len = 0; -+ char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; -+ const char *uri, *addr, *p = data; -+ const char *limit = data + datalen; -+ -+ -+ while (p < limit) { -+ if (strnicmp(p, "\ncontact:", 9) && strnicmp(p, "\nm:", 3) && -+ strnicmp(p, "\rcontact:", 9) && strnicmp(p, "\rm:", 3)) { -+ p++; -+ continue; -+ } -+ -+ while (strnicmp(p, "sip:", 4)) { -+ if (p == limit) -+ return 0; -+ p++; -+ } -+ p += 4; -+ -+ /* If there is user info in the contact */ -+ uri = p; -+ -+ while (*p!='@' && *p!='>' && *p!=';' && *p!='\n' && *p!='\r' && *p!='?' && *p!=',') { -+ if (p == limit) -+ return 0; -+ p++; -+ } -+ -+ if (*p=='@') -+ p++; -+ else -+ p = uri; /* back to previous URI pointer */ -+ -+ /* IP address */ -+ addr = p; -+ -+ /* FQDNs or dotted quads */ -+ while (isalpha(*p) || isdigit(*p) || (*p=='.') || (*p=='-')) { -+ p++; -+ if (p == limit) -+ return 0; -+ } -+ -+ /* If there is a port number, skip it */ -+ if (*p==':') { -+ p++; -+ while (isdigit(*p)) -+ p++; -+ } -+ -+ sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(newip), newport); -+ buflen = strlen(buffer); -+ -+ MUST_BE_LOCKED(&ip_sip_lock); -+ -+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, addr - data, -+ p - addr, buffer, buflen) ) -+ return 0; -+ -+ diff_len = buflen - (p - addr); -+ DEBUGP("(SIP) Contact is changed to %s.\n", buffer); -+ break; -+ } -+ -+ return diff_len; -+} -+ -+static int _find_sip_content_length_size(const char *data, size_t dlen, -+ unsigned int *numoff, unsigned int *numlen) -+{ -+ char *st, *p = (char *)data; -+ const char *limit = data + dlen; -+ int size = 0; -+ -+ while (p < limit) { -+ if (strnicmp(p, "\nContent-Length:", 16) && strnicmp(p, "\nl:", 3) && -+ strnicmp(p, "\rContent-Length:", 16) && strnicmp(p, "\rm:", 3)) { -+ p++; -+ continue; -+ } -+ -+ /* Go through the string above */ -+ while (*p != ':') { -+ if (p == limit) -+ return 0; -+ p++; -+ } -+ p++; -+ -+ while (*p == ' ') { -+ if (p == limit) -+ return 0; -+ p++; -+ } -+ -+ st = p; -+ size = simple_strtoul(p, &p, 10); -+ -+ *numoff = st - data; -+ *numlen = p - st; -+ -+ return size; -+ } -+ -+ return 0; -+} -+ -+static int mangle_sip_content_length(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, -+ struct sk_buff **pskb, int diff_len) -+{ -+ struct iphdr *iph = (*pskb)->nh.iph; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ unsigned int udplen = ntohs(iph->tot_len) - (iph->ihl * 4); -+ unsigned int datalen = udplen - 8; -+ -+ unsigned int matchlen, matchoff; -+ int size, buflen; -+ char buffer[sizeof("nnnnn")]; -+ -+ /* original legth */ -+ size = _find_sip_content_length_size(data, datalen, &matchoff, &matchlen); -+ -+ /* new legth */ -+ sprintf(buffer, "%u", size + diff_len); -+ buflen = strlen(buffer); -+ -+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, matchoff, -+ matchlen, buffer, buflen) ) -+ return 0; -+ -+ DEBUGP("(SDP) Content-Length is changed %d->%s.\n", size, buffer); -+ return buflen - matchlen; -+ -+} -+ -+static int mangle_sip_sdp_content(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, -+ struct sk_buff **pskb, u_int32_t newip, u_int16_t newport) -+{ -+ struct iphdr *iph = (*pskb)->nh.iph; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ unsigned int udplen = ntohs(iph->tot_len) - (iph->ihl * 4); -+ unsigned int datalen = udplen - 8; -+ -+ unsigned int matchlen, matchoff; -+ int found, buflen, diff_len = 0; -+ char buffer[sizeof("nnn.nnn.nnn.nnn")]; -+ char *addr, *p; -+ char *limit = (char *)data + datalen; -+ u_int32_t ipaddr = 0; -+ u_int16_t getport; -+ int dir; -+ -+ /* Find RTP address */ -+ found = find_sdp_rtp_addr(data, datalen, &matchoff, &matchlen, &ipaddr); -+ if (found) { -+ /* If it's a null address, then the call is on hold */ -+ if (found == 2 && ipaddr == 0) -+ return 0; -+ -+ sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); -+ buflen = strlen(buffer); -+ -+ MUST_BE_LOCKED(&ip_sip_lock); -+ -+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, matchoff, -+ matchlen, buffer, buflen) ) -+ return 0; -+ -+ diff_len += (buflen - matchlen); -+ DEBUGP("(SDP) RTP address is changed to %s.\n", buffer); -+ } -+ -+ /* Find audio port */ -+ getport = find_sdp_audio_port(data, datalen, &matchoff, &matchlen); -+ if (getport != newport) { -+ sprintf(buffer, "%d", newport); -+ buflen = strlen(buffer); -+ -+ MUST_BE_LOCKED(&ip_sip_lock); -+ -+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, matchoff, -+ matchlen, buffer, buflen) ) -+ return 0; -+ -+ diff_len += (buflen - matchlen); -+ DEBUGP("(SDP) audio port is changed to %d.\n", newport); -+ } -+ -+ dir = CTINFO2DIR(ctinfo); -+ if (dir == IP_CT_DIR_ORIGINAL) -+ return diff_len; -+ -+ /* Find Session ID address */ -+ found = find_pattern(data, datalen, " IN IP4 ", 8, ' ', '\r', -+ &matchoff, &matchlen); -+ if (found) { -+ p = addr = (char *)data + matchoff; -+ -+ /* FQDNs or dotted quads */ -+ while (isalpha(*p) || isdigit(*p) || (*p=='.') || (*p=='-')) { -+ p++; -+ if (p == limit) -+ return 0; -+ } -+ -+ sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); -+ buflen = strlen(buffer); -+ -+ MUST_BE_LOCKED(&ip_sip_lock); -+ -+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, addr - data, -+ p - addr, buffer, buflen) ) -+ return 0; -+ -+ diff_len += (buflen - (p - addr)); -+ DEBUGP("(SDP) Session ID is changed to %s.\n", buffer); -+ } -+ -+ return diff_len; -+} -+ -+static int mangle_sip_packet(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, -+ struct sk_buff **pskb, u_int32_t newip) -+{ -+ struct iphdr *iph = (*pskb)->nh.iph; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ int diff_len = 0; -+ struct ip_ct_sip_master *ct_sip_info = &ct->help.ct_sip_info; -+ u_int16_t natport = ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port); -+ -+ DEBUGP("nat_sip: %s:(%d)\n", __FUNCTION__, __LINE__); -+ -+ ct_sip_info->mangled = 1; -+ -+ /* Changes the via, if this is a request */ -+ if (strnicmp(data,"SIP/2.0",7) != 0) { -+ mangle_sip_via(ct, ctinfo, pskb, newip, natport); -+ } -+ -+ mangle_sip_contact(ct, ctinfo, pskb, newip, natport); -+ -+ if ((diff_len = mangle_sip_sdp_content(ct, ctinfo, pskb, newip, ct_sip_info->rtpport)) != 0) -+ mangle_sip_content_length(ct, ctinfo, pskb, diff_len); -+ -+ return 1; -+} -+ -+static struct ip_conntrack_expect * -+expect_find(struct ip_conntrack *ct, u_int32_t dstip, u_int16_t dstport) -+{ -+ const struct ip_conntrack_tuple tuple = { { 0, { 0 } }, -+ { dstip, { htons(dstport) }, IPPROTO_UDP }}; -+ -+ return ip_conntrack_expect_find_get(&tuple); -+ -+} -+ -+static int sip_out_data_fixup(struct ip_conntrack *ct, -+ struct sk_buff **pskb, -+ enum ip_conntrack_info ctinfo, -+ struct ip_conntrack_expect *expect) -+{ -+ struct ip_conntrack_tuple newtuple; -+ struct ip_ct_sip_master *ct_sip_info = &ct->help.ct_sip_info; -+ struct ip_ct_sip_expect *exp_sip_info; -+ u_int32_t wanip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; // NAT wan ip -+ u_int16_t port = 0; -+#ifdef RTCP_SUPPORT -+ struct ip_conntrack_expect *rtcp_exp; -+#endif -+ -+ MUST_BE_LOCKED(&ip_sip_lock); -+ -+ if (expect) { -+ DEBUGP("nat_sip: %s: There is a exp %p.\n", __FUNCTION__, expect); -+ -+ exp_sip_info = &expect->help.exp_sip_info; -+ if (exp_sip_info->nated) { -+ DEBUGP("nat_sip: %s: The exp %p had been changed.\n", __FUNCTION__, expect); -+ goto mangle; -+ } -+ -+ /* RTP expect */ -+ if (exp_sip_info->type == CONN_RTP) { -+ port = ntohs(expect->tuple.dst.u.udp.port); -+#ifdef RTCP_SUPPORT -+ rtcp_exp = expect_find(ct, expect->tuple.dst.ip, port + 1); -+#endif -+ /* RFC1889 - If an application is supplied with an odd number -+ * for use as the RTP port, it should replace this number with -+ * the next lower (even) number. */ -+ if (port % 2) -+ port++; -+ -+ /* fullfill newtuple */ -+ newtuple.dst.ip = wanip; -+ newtuple.src.ip = expect->tuple.src.ip; -+ newtuple.dst.protonum = expect->tuple.dst.protonum; -+ -+ /* Try to get same port: if not, try to change it. */ -+ for (; port != 0; port += 2) { -+ newtuple.dst.u.udp.port = htons(port); -+ if (ip_conntrack_change_expect(expect, &newtuple) == 0) { -+#ifdef RTCP_SUPPORT -+ /* Change RTCP */ -+ if (rtcp_exp) { -+ DEBUGP("nat_sip: %s: RTCP exp %p found.\n", -+ __FUNCTION__, rtcp_exp); -+ newtuple.dst.u.udp.port = htons(port + 1); -+ if (ip_conntrack_change_expect(rtcp_exp, &newtuple) != 0) { -+ DEBUGP("nat_sip: %s: Can't change RTCP exp %p.\n", -+ __FUNCTION__, rtcp_exp); -+ continue; -+ } -+ rtcp_exp->help.exp_sip_info.nated = 1; -+ } -+#endif -+ break; -+ } -+ } -+ if (port == 0) -+ return 0; -+ -+ exp_sip_info->nated = 1; -+ ct_sip_info->rtpport = port; -+ DEBUGP("nat_sip: %s: RTP exp %p, masq port=%d\n", __FUNCTION__, expect, port); -+ } -+#ifdef RTCP_SUPPORT -+ else { -+ /* We ignore the RTCP expect, and will adjust it later -+ * during RTP expect */ -+ DEBUGP("nat_sip: %s: RTCP exp %p, by-pass.\n", __FUNCTION__, expect); -+ return 1; -+ } -+#endif -+ } -+ -+mangle: -+ /* Change address inside packet to match way we're mapping -+ this connection. */ -+ if (!ct_sip_info->mangled) -+ if (!mangle_sip_packet(ct, ctinfo, pskb, wanip)) -+ return 0; -+ -+ return 1; -+} -+ -+static int sip_in_data_fixup(struct ip_conntrack *ct, -+ struct sk_buff **pskb, -+ enum ip_conntrack_info ctinfo, -+ struct ip_conntrack_expect *expect) -+{ -+ struct iphdr *iph = (*pskb)->nh.iph; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ unsigned int udplen = ntohs(iph->tot_len) - (iph->ihl * 4); -+ unsigned int datalen = udplen - 8; -+ struct ip_ct_sip_master *ct_sip_info = &ct->help.ct_sip_info; -+ u_int32_t wanip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; // NAT wan ip -+ unsigned int matchlen, matchoff; -+ int found, diff_len = 0; -+ u_int32_t ipaddr = 0, vip = 0; -+ u_int16_t port = 0, vport = 0, aport = 0; -+ struct ip_conntrack_expect *exp; -+#ifdef RTCP_SUPPORT -+ struct ip_conntrack_expect *rtcpexp; -+#endif -+ -+ if (expect) -+ DEBUGP("nat_sip: %s: There is a exp %p.\n", __FUNCTION__, expect); -+ -+ /* Prevent from mangling the packet or expect twice */ -+ if (ct_sip_info->mangled) -+ return 1; -+ -+ ct_sip_info->mangled = 1; -+ -+ if (strnicmp(data, "SIP/2.0 200", 11) == 0) { -+ /* Find CSeq field */ -+ found = find_pattern(data, datalen, "CSeq: ", 6, ' ', '\r', -+ &matchoff, &matchlen); -+ if (found) { -+ char *p = (char *)data + matchoff; -+ -+ simple_strtoul(p, &p, 10); -+ if (strnicmp(p, " REGISTER", 9) == 0) { -+ DEBUGP("nat_sip: 200 OK - REGISTER\n"); -+ vip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; -+ vport = ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port); -+ mangle_sip_via(ct, ctinfo, pskb, vip, vport); -+ mangle_sip_contact(ct, ctinfo, pskb, vip, vport); -+ return 1; -+ } -+ } -+ } -+ -+ /* Only interesting the SDP content. */ -+ if (strnicmp(data, "INVITE", 6) != 0 && strnicmp(data, "SIP/2.0 200", 11) != 0) -+ return 1; -+ -+ /* Find RTP address */ -+ found = find_sdp_rtp_addr(data, datalen, &matchoff, &matchlen, &ipaddr); -+ -+ DEBUGP("nat_sip: sdp address found = %d, ipaddr = %u.\n", found, ipaddr); -+ if (found < 2) -+ return 1; -+ -+ /* Is it a null address or our WAN address? */ -+ if (ipaddr == 0 || (htonl(ipaddr) != wanip)) -+ return 1; -+ -+ DEBUGP("nat_sip: %s: This is a lookback RTP connection.\n", __FUNCTION__); -+ -+ /* Find audio port, and we don't like the well-known ports, -+ * which is less than 1024 */ -+ port = find_sdp_audio_port(data, datalen, &matchoff, &matchlen); -+ if (port < 1024) -+ return 0; -+ -+ exp = expect_find(ct, wanip, port); -+ if (exp) { -+ DEBUGP("nat_sip: %s: Found exp %p, tuple.dst=%u.%u.%u.%u:%u.\n", -+ __FUNCTION__, exp, NIPQUAD(ipaddr), port); -+ -+ /* Restore masq-ed SDP */ -+ vip = exp->expectant->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; -+ aport = exp->help.exp_sip_info.port; -+ if ((diff_len = mangle_sip_sdp_content(ct, ctinfo, pskb, vip, aport)) != 0) -+ mangle_sip_content_length(ct, ctinfo, pskb, diff_len); -+ -+ /* Unset RTP, RTCP expect, respectively */ -+ ip_conntrack_unexpect_related(exp); -+#ifdef RTCP_SUPPORT -+ rtcpexp = expect_find(ct, wanip, port + 1); -+ if (rtcpexp) -+ ip_conntrack_unexpect_related(rtcpexp); -+#endif -+ } -+ -+ return 1; -+} -+ -+static unsigned int nat_help(struct ip_conntrack *ct, -+ struct ip_conntrack_expect *exp, -+ struct ip_nat_info *info, -+ enum ip_conntrack_info ctinfo, -+ unsigned int hooknum, -+ struct sk_buff **pskb) -+{ -+ int dir; -+ struct iphdr *iph = (*pskb)->nh.iph; -+ struct udphdr *udph = (void *)iph + iph->ihl * 4; -+ const char *data = (const char *)udph + 8; -+ -+ /* Only mangle things once: original direction in POST_ROUTING -+ and reply direction on PRE_ROUTING. */ -+ dir = CTINFO2DIR(ctinfo); -+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL) -+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) { -+ DEBUGP("nat_sip: Not touching dir %s at hook %s\n", -+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY", -+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING" -+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING" -+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"); -+ return NF_ACCEPT; -+ } -+ -+ if (strnicmp(data, "REGISTER" , 8) == 0) -+ DEBUGP("nat_sip: REGISTER\n"); -+ else if (strnicmp(data, "INVITE" , 6) == 0) -+ DEBUGP("nat_sip: INVITE\n"); -+ else if (strnicmp(data, "ACK" , 3) == 0) -+ DEBUGP("nat_sip: ACK\n"); -+ else if (strnicmp(data, "BYE", 3) == 0) -+ DEBUGP("nat_sip: BYE\n"); -+ else if (strnicmp(data, "SIP/2.0 200", 11) == 0) -+ DEBUGP("nat_sip: 200 OK\n"); -+ else if (strnicmp(data, "SIP/2.0 100", 11) == 0) -+ DEBUGP("nat_sip: 100 Trying\n"); -+ else if (strnicmp(data, "SIP/2.0 180", 11) == 0) -+ DEBUGP("nat_sip: 180 Ringing\n"); -+ -+ LOCK_BH(&ip_sip_lock); -+ -+ if (dir == IP_CT_DIR_ORIGINAL) -+ sip_out_data_fixup(ct, pskb, ctinfo, exp); -+ else -+ sip_in_data_fixup(ct, pskb, ctinfo, exp); -+ -+ UNLOCK_BH(&ip_sip_lock); -+ -+ return NF_ACCEPT; -+} -+ -+static struct ip_nat_helper sip[MAX_PORTS]; -+static char sip_names[MAX_PORTS][6]; -+ -+/* Not __exit: called from init() */ -+static void fini(void) -+{ -+ int i; -+ -+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { -+ DEBUGP("ip_nat_sip: unregistering port %d\n", ports[i]); -+ ip_nat_helper_unregister(&sip[i]); -+ } -+} -+ -+static int __init init(void) -+{ -+ int i, ret=0; -+ char *tmpname; -+ -+ if (ports[0] == 0) -+ ports[0] = SIP_PORT; -+ -+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { -+ -+ memset(&sip[i], 0, sizeof(struct ip_nat_helper)); -+ -+ sip[i].tuple.dst.u.udp.port = htons(ports[i]); -+ sip[i].tuple.dst.protonum = IPPROTO_UDP; -+ sip[i].mask.dst.u.udp.port = 0xF0FF; -+ sip[i].mask.dst.protonum = 0xFFFF; -+ sip[i].help = nat_help; -+ sip[i].expect = sip_nat_expected; -+ sip[i].flags = IP_NAT_HELPER_F_ALWAYS; -+ -+ tmpname = &sip_names[i][0]; -+ sprintf(tmpname, "sip%2.2d", i); -+ sip[i].name = tmpname; -+ -+ DEBUGP("ip_nat_sip: Trying to register for port %d\n", -+ ports[i]); -+ ret = ip_nat_helper_register(&sip[i]); -+ -+ if (ret) { -+ printk("ip_nat_sip: error registering " -+ "helper for port %d\n", ports[i]); -+ fini(); -+ return ret; -+ } -+ ports_c++; -+ } -+ -+ return ret; -+} -+ -+module_init(init); -+module_exit(fini); -diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.new/net/ipv4/netfilter/Makefile ---- linux-2.4.32/net/ipv4/netfilter/Makefile 2006-02-04 19:16:25.000000000 +0100 -+++ linux-2.4.32.new/net/ipv4/netfilter/Makefile 2006-02-04 19:00:13.000000000 +0100 -@@ -53,6 +53,10 @@ - ifdef CONFIG_IP_NF_NAT_PPTP - export-objs += ip_conntrack_pptp.o - endif -+obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o -+ifdef CONFIG_IP_NF_NAT_SIP -+ export-objs += ip_conntrack_sip.o -+endif - - - # NAT helpers -@@ -62,6 +66,7 @@ - obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o - obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o - obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o -+obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o - - # generic IP tables - obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o -diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h ---- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h 2006-02-04 19:16:25.000000000 +0100 -+++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-02-04 19:00:13.000000000 +0100 -@@ -71,6 +71,7 @@ - #include <linux/netfilter_ipv4/ip_conntrack_ftp.h> - #include <linux/netfilter_ipv4/ip_conntrack_irc.h> - #include <linux/netfilter_ipv4/ip_conntrack_pptp.h> -+#include <linux/netfilter_ipv4/ip_conntrack_sip.h> - - /* per expectation: application helper private data */ - union ip_conntrack_expect_help { -@@ -79,6 +80,7 @@ - struct ip_ct_ftp_expect exp_ftp_info; - struct ip_ct_irc_expect exp_irc_info; - struct ip_ct_pptp_expect exp_pptp_info; -+ struct ip_ct_sip_expect exp_sip_info; - - #ifdef CONFIG_IP_NF_NAT_NEEDED - union { -@@ -93,6 +95,7 @@ - struct ip_ct_ftp_master ct_ftp_info; - struct ip_ct_irc_master ct_irc_info; - struct ip_ct_pptp_master ct_pptp_info; -+ struct ip_ct_sip_master ct_sip_info; - }; - - #ifdef CONFIG_IP_NF_NAT_NEEDED -diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_sip.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_sip.h ---- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_sip.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_sip.h 2006-02-04 19:00:13.000000000 +0100 -@@ -0,0 +1,56 @@ -+#ifndef _IP_CONNTRACK_SIP_H -+#define _IP_CONNTRACK_SIP_H -+/* SIP tracking. */ -+ -+#ifdef __KERNEL__ -+ -+#include <linux/netfilter_ipv4/lockhelp.h> -+ -+/* Protects sip part of conntracks */ -+DECLARE_LOCK_EXTERN(ip_sip_lock); -+ -+#define SIP_PORT 5060 /* UDP */ -+#define SIP_EXPIRES 3600 /* seconds */ -+#define RTP_TIMEOUT 180 /* seconds */ -+ -+#endif /* __KERNEL__ */ -+ -+/* SIP Request */ -+#define SIP_INVITE 0x01 -+#define SIP_ACK 0x02 -+#define SIP_BYE 0x04 -+/* SIP Response */ -+#define SIP_100 0x10 -+#define SIP_200 0x20 -+#define SIP_200_BYE 0x40 -+/* SIP session direction */ -+#define SIP_OUTGOING 0 -+#define SIP_INCOMING 1 -+ -+enum ip_ct_conntype -+{ -+ CONN_SIP, -+ CONN_RTP, -+ CONN_RTCP, -+}; -+ -+/* This structure is per expected connection */ -+struct ip_ct_sip_expect -+{ -+ u_int16_t port; /* TCP port that was to be used */ -+ -+ enum ip_ct_conntype type; -+ int nated; -+}; -+ -+/* This structure exists only once per master */ -+struct ip_ct_sip_master { -+ int mangled; -+ u_int16_t rtpport; -+}; -+ -+extern u_int16_t find_sdp_audio_port(const char *data, size_t dlen, -+ unsigned int *numoff, unsigned int *numlen); -+extern int find_sdp_rtp_addr(const char *data, size_t dlen, -+ unsigned int *numoff, unsigned int *numlen, u_int32_t *addr); -+#endif /* _IP_CONNTRACK_SIP_H */ |