Michael,

I am not the maintainer of the NAT-SIP module. In the future, you should post similar requests to the linux-net mailinglist where it can be picked up by more skilled people. I have cross-posted my reply there too.

The problem you describe is one of the reasons why, in general, you shouldn't run SIP over NAT. However, I have attached a crude patch that you can try that solved a similar problem for me. The patch applies against current 2.6.21.5 source. If you want to use the patch for anything earlier than 2.6.21.5, then you also need the patch that I included at the very end of this reply.

Regards,
Jerome Borsboom


--- linux-2.6.21.5/net/ipv4/netfilter/nf_nat_sip.c      2007-01-18 
21:09:30.000000000 +0100
+++ linux-2.6.21.5.new/net/ipv4/netfilter/nf_nat_sip.c  2007-01-20 
13:44:14.000000000 +0100
@@ -67,7 +67,8 @@

 static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
                        struct nf_conn *ct, const char **dptr, size_t dlen,
-                       enum sip_header_pos pos, struct addr_map *map)
+                       enum sip_header_pos pos, struct addr_map *map,
+                       struct nf_conntrack_expect *exp)
 {
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
        unsigned int matchlen, matchoff, addrlen;
@@ -81,6 +82,8 @@
            memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
                addr    = map->addr[!dir].dst;
                addrlen = map->addr[!dir].dstlen;
+               if (exp)
+                       exp->tuple.dst.u3.ip  = 
ct->tuplehash[!dir].tuple.dst.u3.ip;
        } else if ((matchlen == map->addr[dir].dstiplen ||
                    matchlen == map->addr[dir].dstlen) &&
                   memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) 
{
@@ -126,14 +129,14 @@
                else
                        pos = POS_REQ_URI;

-               if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
+               if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map, 
NULL))
                        return NF_DROP;
        }

-       if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
-           !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
-           !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
-           !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
+       if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map, 
NULL) ||
+           !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map, NULL) 
||
+           !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map, NULL) 
||
+           !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map, 
NULL))
                return NF_DROP;
        return NF_ACCEPT;
 }
@@ -194,23 +197,35 @@
 static unsigned int mangle_sdp(struct sk_buff **pskb,
                               enum ip_conntrack_info ctinfo,
                               struct nf_conn *ct,
-                              __be32 newip, u_int16_t port,
-                              const char *dptr)
+                              const char *dptr,
+                              struct nf_conntrack_expect *exp)
 {
-       char buffer[sizeof("nnn.nnn.nnn.nnn")];
-       unsigned int dataoff, bufflen;
+       struct addr_map map;
+       unsigned int dataoff, datalen;

        dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+       datalen = (*pskb)->len - dataoff;
+
+       addr_map_init(ct, &map);

        /* Mangle owner and contact info. */
-       bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
-       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-                              buffer, bufflen, POS_OWNER_IP4))
+       if (!map_sip_addr(pskb, ctinfo, ct, &dptr, datalen, POS_OWNER_IP4, 
&map, NULL) ||
+           !map_sip_addr(pskb, ctinfo, ct, &dptr, datalen, POS_CONNECTION_IP4, 
&map, exp))
                return 0;

-       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-                              buffer, bufflen, POS_CONNECTION_IP4))
-               return 0;
+       return mangle_content_len(pskb, ctinfo, ct, dptr);
+}
+
+static unsigned int mangle_sdp_port(struct sk_buff **pskb,
+                              enum ip_conntrack_info ctinfo,
+                              struct nf_conn *ct,
+                              u_int16_t port,
+                              const char *dptr)
+{
+       char buffer[sizeof("nnnnn")];
+       unsigned int dataoff, bufflen;
+
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);

        /* Mangle media port. */
        bufflen = sprintf(buffer, "%u", port);
@@ -221,6 +236,36 @@
        return mangle_content_len(pskb, ctinfo, ct, dptr);
 }

+static void nf_nat_follow_sip(struct nf_conn *ct,
+                          struct nf_conntrack_expect *exp)
+{
+        struct nf_nat_range range;
+
+        /* This must be a fresh one. */
+        BUG_ON(ct->status & IPS_NAT_DONE_MASK);
+
+       if (ct->tuplehash[exp->dir].tuple.src.u3.ip ==
+               ct->master->tuplehash[exp->dir].tuple.src.u3.ip) {
+               /* Change src to where master sends to */
+               range.flags = IP_NAT_RANGE_MAP_IPS;
+               range.min_ip = range.max_ip
+                       = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+               /* hook doesn't matter, but it has to do source manip */
+               nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+       }
+
+       if (ct->tuplehash[exp->dir].tuple.dst.u3.ip ==
+               ct->master->tuplehash[exp->dir].tuple.dst.u3.ip) {
+               /* For DST manip, map port here to where it's expected. */
+               range.flags = (IP_NAT_RANGE_MAP_IPS | 
IP_NAT_RANGE_PROTO_SPECIFIED);
+               range.min = range.max = exp->saved_proto;
+               range.min_ip = range.max_ip
+                       = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
+               /* hook doesn't matter, but it has to do destination manip */
+               nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+       }
+}
+
 /* 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_sdp(struct sk_buff **pskb,
@@ -230,21 +275,20 @@
 {
        struct nf_conn *ct = exp->master;
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-       __be32 newip;
        u_int16_t port;

        DEBUGP("ip_nat_sdp():\n");

-       /* Connection will come from reply */
-       newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+       if (!mangle_sdp(pskb, ctinfo, ct, dptr, exp))
+               return NF_DROP;

-       exp->tuple.dst.u3.ip = newip;
+       /* Connection will come from reply */
        exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
        exp->dir = !dir;

        /* When you see the packet, we need to NAT it the same as the
           this one. */
-       exp->expectfn = nf_nat_follow_master;
+       exp->expectfn = nf_nat_follow_sip;

        /* Try to get same port: if not, try to change it. */
        for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
@@ -256,7 +300,7 @@
        if (port == 0)
                return NF_DROP;

-       if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
+       if (!mangle_sdp_port(pskb, ctinfo, ct, port, dptr)) {
                nf_conntrack_unexpect_related(exp);
                return NF_DROP;
        }
--- linux-2.6.21.5/net/netfilter/nf_conntrack_sip.c     2007-01-18 
21:09:30.000000000 +0100
+++ linux-2.6.21.5.new/net/netfilter/nf_conntrack_sip.c 2007-01-26 
22:45:31.000000000 +0100
@@ -376,7 +376,7 @@
        if (exp == NULL)
                return NF_DROP;
        nf_conntrack_expect_init(exp, family,
-                                &ct->tuplehash[!dir].tuple.src.u3, addr,
+                                NULL, addr,
                                 IPPROTO_UDP, NULL, &port);

        nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
@@ -436,6 +436,8 @@

        /* RTP info only in some SDP pkts */
        if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+           memcmp(dptr, "SIP/2.0 180", sizeof("SIP/2.0 180") - 1) != 0 &&
+           memcmp(dptr, "SIP/2.0 183", sizeof("SIP/2.0 183") - 1) != 0 &&
            memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
                goto out;
        }

On Mon, 11 Jun 2007, Michael Rack wrote:

Dear Mr. Borsboom,

my name is Michael Rack, i'm from Germany. Sorry, if this is not the right place for my bug report. But i hope you can post it on the right place.

*Now to the problem:*
If the SIP-Server is running on (217.10.79.9) and the Audio-Stream-Server on (217.10.79.30), the NAT_SIP Module is get into trouble.

*The SIP-Message from Service-Provider to my GATEWAY look like this (**91.64.xxx.xxx is my gateway):*
00:46:12 IP 217.10.79.9.5060 > 91.64.xxx.xxx.5060: SIP, length: 821
SIP/2.0 200 OK
Via: SIP/2.0/UDP 91.64.xxx.xxx:5060;branch=z9hG4bK12EC1F9F577AE583
Record-Route: <sip:217.10.79.9;lr=on>
From: <sip:[EMAIL PROTECTED]>;tag=ECA70DB358408E40
To: <sip:[EMAIL PROTECTED]>;tag=as0a188b3b
Call-ID: [EMAIL PROTECTED]
CSeq: 14 INVITE
User-Agent: sipgate GW v.23.42
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY
Supported: replaces
Contact: <sip:[EMAIL PROTECTED]>
Content-Type: application/sdp
Content-Length: 334

v=0
o=root 8988 8988 IN IP4 217.10.79.30
s=session
c=IN IP4 217.10.79.30
t=0 0
m=audio 15634 RTP/AVP 8 0 97 2 101
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:97 iLBC/8000
a=fmtp:97 mode=30
a=rtpmap:2 G726-32/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=silenceSupp:off - - - -
a=ptime:20
a=sendrecv

*The SIP-Message forwarded to the SIP-DEVICE (10.10.202.2 is my Fritz!Box Fon 5010**):
*01:00:32.638894 IP 217.10.79.9.5060 > 10.10.202.2.5060: SIP, length: 819
SIP/2.0 200 OK
Via: SIP/2.0/UDP 91.64.xxx.xxx:5060;branch=z9hG4bK41AD3D8FB0A8A5F7
Record-Route: <sip:217.10.79.9;lr=on>
From: <sip:[EMAIL PROTECTED]>;tag=F0668B35CFE4136D
To: <sip:[EMAIL PROTECTED]>;tag=as508e8403
Call-ID: [EMAIL PROTECTED]
CSeq: 17 INVITE
User-Agent: sipgate GW v.23.42
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY
Supported: replaces
Contact: <sip:[EMAIL PROTECTED]>
Content-Type: application/sdp
Content-Length: 332

v=0
o=root 8988 8988 IN IP4 217.10.79.9
s=session
c=IN IP4 217.10.79.9
t=0 0
m=audio 15634 RTP/AVP 8 0 97 2 101
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:97 iLBC/8000
a=fmtp:97 mode=30
a=rtpmap:2 G726-32/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=silenceSupp:off - - - -
a=ptime:20
a=sendrecv

Now, you will see, the IP-Address has been changed, while the packet was processed by NAT_SIP Module. The IP-Addresss 217.10.79.9:15634 is not correct. The correct Address is 217.10.79.30:15634 ... What to the hell is there going on?

In this state, any AUDIO-Stream takes the wrong way!

*This is a snapshot of the audio connection beetween SIP-DEVICE and GATEWAY:*
00:46:19.478583 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252
00:46:19.510688 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252
00:46:19.542658 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252
00:46:19.566317 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252
00:46:19.598344 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252
00:46:19.630361 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252
00:46:19.662327 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252
00:46:19.686704 IP 10.10.202.2.7078 > 217.10.79.9.15634: UDP, length 252

*This is a snapshot of the audio connection beetween SIP-PROVIDER and GATEWAY:*
01:08:59.825647 IP 217.10.79.30.15634 > 91.64.105.116.7078: UDP, length 172
01:08:59.837486 IP 91.64.105.116.7078 > 217.10.79.9.15634: UDP, length 252
01:08:59.845643 IP 217.10.79.30.15634 > 91.64.105.116.7078: UDP, length 172
01:08:59.860817 IP 91.64.105.116.7078 > 217.10.79.9.15634: UDP, length 252
01:08:59.865664 IP 217.10.79.30.15634 > 91.64.105.116.7078: UDP, length 172
01:08:59.885723 IP 217.10.79.30.15634 > 91.64.105.116.7078: UDP, length 172
01:08:59.892855 IP 91.64.105.116.7078 > 217.10.79.9.15634: UDP, length 252
01:08:59.905692 IP 217.10.79.30.15634 > 91.64.105.116.7078: UDP, length 172
01:08:59.924852 IP 91.64.105.116.7078 > 217.10.79.9.15634: UDP, length 252
01:08:59.925667 IP 217.10.79.30.15634 > 91.64.105.116.7078: UDP, length 172
01:08:59.945473 IP 217.10.79.30.15634 > 91.64.105.116.7078: UDP, length 172
01:08:59.957156 IP 91.64.105.116.7078 > 217.10.79.9.15634: UDP, length 252

NOW THIS IS A VERY BIG PROBLEM...

Kind regards,
Michael Rack
Germany




--- linux-2.6.20/net/core/utils.c       2007-02-04 19:44:54.000000000 +0100
+++ linux-2.6.20/net/core/utils.c       2007-04-15 21:08:55.000000000 +0200
@@ -137,16 +137,16 @@
        while(1) {
                int c;
                c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
-               if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM))) {
+               if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | 
IN6PTON_COLON_MASK))) {
                        goto out;
                }
-               if (c & (IN6PTON_DOT | IN6PTON_DELIM)) {
+               if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
                        if (w == 0)
                                goto out;
                        *d++ = w & 0xff;
                        w = 0;
                        i++;
-                       if (c & IN6PTON_DELIM) {
+                       if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
                                if (i != 4)
                                        goto out;
                                break;
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to