unsigned int *datalen) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
 
-void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off) __read_mostly;
+void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, unsigned int protoff,
+                                  s16 off) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_sip_seq_adjust_hook);
 
 unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
  * be tolerant and also accept records terminated with a single newline
  * character". We handle both cases.
  */
-static const struct sip_header ct_sdp_hdrs[] = {
-       [SDP_HDR_VERSION]               = SDP_HDR("v=", NULL, digits_len),
-       [SDP_HDR_OWNER_IP4]             = SDP_HDR("o=", "IN IP4 ", sdp_addr_len),
-       [SDP_HDR_CONNECTION_IP4]        = SDP_HDR("c=", "IN IP4 ", sdp_addr_len),
-       [SDP_HDR_OWNER_IP6]             = SDP_HDR("o=", "IN IP6 ", sdp_addr_len),
-       [SDP_HDR_CONNECTION_IP6]        = SDP_HDR("c=", "IN IP6 ", sdp_addr_len),
-       [SDP_HDR_MEDIA]                 = SDP_HDR("m=", NULL, media_len),
+static const struct sip_header ct_sdp_hdrs_v4[] = {
+       [SDP_HDR_VERSION]       = SDP_HDR("v=", NULL, digits_len),
+       [SDP_HDR_OWNER]         = SDP_HDR("o=", "IN IP4 ", sdp_addr_len),
+       [SDP_HDR_CONNECTION]    = SDP_HDR("c=", "IN IP4 ", sdp_addr_len),
+       [SDP_HDR_MEDIA]         = SDP_HDR("m=", NULL, media_len),
+};
+
+static const struct sip_header ct_sdp_hdrs_v6[] = {
+       [SDP_HDR_VERSION]       = SDP_HDR("v=", NULL, digits_len),
+       [SDP_HDR_OWNER]         = SDP_HDR("o=", "IN IP6 ", sdp_addr_len),
+       [SDP_HDR_CONNECTION]    = SDP_HDR("c=", "IN IP6 ", sdp_addr_len),
+       [SDP_HDR_MEDIA]         = SDP_HDR("m=", NULL, media_len),
 };
 
 /* Linear string search within SDP header values */
                          enum sdp_header_types term,
                          unsigned int *matchoff, unsigned int *matchlen)
 {
-       const struct sip_header *hdr = &ct_sdp_hdrs[type];
-       const struct sip_header *thdr = &ct_sdp_hdrs[term];
+       const struct sip_header *hdrs, *hdr, *thdr;
        const char *start = dptr, *limit = dptr + datalen;
        int shift = 0;
 
+       hdrs = nf_ct_l3num(ct) == NFPROTO_IPV4 ? ct_sdp_hdrs_v4 : ct_sdp_hdrs_v6;
+       hdr = &hdrs[type];
+       thdr = &hdrs[term];
+
        for (dptr += dataoff; dptr < limit; dptr++) {
                /* Find beginning of line */
                if (*dptr != '\r' && *dptr != '\n')
                    exp->class != class)
                        break;
 #ifdef CONFIG_NF_NAT_NEEDED
-               if (exp->tuple.src.l3num == AF_INET && !direct_rtp &&
-                   (exp->saved_addr.ip != exp->tuple.dst.u3.ip ||
+               if (!direct_rtp &&
+                   (!nf_inet_addr_cmp(&exp->saved_addr, &exp->tuple.dst.u3) ||
                     exp->saved_proto.udp.port != exp->tuple.dst.u.udp.port) &&
                    ct->status & IPS_NAT_MASK) {
-                       daddr->ip               = exp->saved_addr.ip;
-                       tuple.dst.u3.ip         = exp->saved_addr.ip;
+                       *daddr                  = exp->saved_addr;
+                       tuple.dst.u3            = exp->saved_addr;
                        tuple.dst.u.udp.port    = exp->saved_proto.udp.port;
                        direct_rtp = 1;
                } else
                          IPPROTO_UDP, NULL, &rtcp_port);
 
        nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
-       if (nf_nat_sdp_media && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
-           ct->status & IPS_NAT_MASK && !direct_rtp)
+       if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp)
                ret = nf_nat_sdp_media(skb, protoff, dataoff, dptr, datalen,
                                       rtp_exp, rtcp_exp,
                                       mediaoff, medialen, daddr);
        unsigned int i;
        union nf_inet_addr caddr, maddr, rtp_addr;
        unsigned int port;
-       enum sdp_header_types c_hdr;
        const struct sdp_media_type *t;
        int ret = NF_ACCEPT;
        typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr;
        typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session;
 
        nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook);
-       c_hdr = nf_ct_l3num(ct) == AF_INET ? SDP_HDR_CONNECTION_IP4 :
-                                            SDP_HDR_CONNECTION_IP6;
 
        /* Find beginning of session description */
        if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
         * the end of the session description. */
        caddr_len = 0;
        if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen,
-                                 c_hdr, SDP_HDR_MEDIA,
+                                 SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
                                  &matchoff, &matchlen, &caddr) > 0)
                caddr_len = matchlen;
 
                /* The media description overrides the session description. */
                maddr_len = 0;
                if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen,
-                                         c_hdr, SDP_HDR_MEDIA,
+                                         SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
                                          &matchoff, &matchlen, &maddr) > 0) {
                        maddr_len = matchlen;
                        memcpy(&rtp_addr, &maddr, sizeof(rtp_addr));
                        return ret;
 
                /* Update media connection address if present */
-               if (maddr_len && nf_nat_sdp_addr &&
-                   nf_ct_l3num(ct) == NFPROTO_IPV4 && ct->status & IPS_NAT_MASK) {
+               if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
                        ret = nf_nat_sdp_addr(skb, protoff, dataoff,
-                                             dptr, datalen,
-                                             mediaoff, c_hdr, SDP_HDR_MEDIA,
+                                             dptr, datalen, mediaoff,
+                                             SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
                                              &rtp_addr);
                        if (ret != NF_ACCEPT)
                                return ret;
 
        /* Update session connection and owner addresses */
        nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
-       if (nf_nat_sdp_session && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
-           ct->status & IPS_NAT_MASK)
+       if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
                ret = nf_nat_sdp_session(skb, protoff, dataoff,
                                         dptr, datalen, sdpoff, &rtp_addr);
 
        exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
 
        nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
-       if (nf_nat_sip_expect && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
-           ct->status & IPS_NAT_MASK)
+       if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK)
                ret = nf_nat_sip_expect(skb, protoff, dataoff, dptr, datalen,
                                        exp, matchoff, matchlen);
        else {
        else
                ret = process_sip_response(skb, protoff, dataoff, dptr, datalen);
 
-       if (ret == NF_ACCEPT && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
-           ct->status & IPS_NAT_MASK) {
+       if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
                nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
                if (nf_nat_sip && !nf_nat_sip(skb, protoff, dataoff,
                                              dptr, datalen))
                datalen  = datalen + diff - msglen;
        }
 
-       if (ret == NF_ACCEPT && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
-           ct->status & IPS_NAT_MASK) {
+       if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
                nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook);
                if (nf_nat_sip_seq_adjust)
-                       nf_nat_sip_seq_adjust(skb, tdiff);
+                       nf_nat_sip_seq_adjust(skb, protoff, tdiff);
        }
 
        return ret;
 
  * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
  * based on RR's ip_nat_ftp.c and other modules.
  * (C) 2007 United Security Providers
- * (C) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ * (C) 2007, 2008, 2011, 2012 Patrick McHardy <kaber@trash.net>
  *
  * 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
 
 #include <linux/module.h>
 #include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <net/ip.h>
+#include <linux/inet.h>
 #include <linux/udp.h>
 #include <linux/tcp.h>
 
        unsigned int baseoff;
 
        if (nf_ct_protonum(ct) == IPPROTO_TCP) {
-               th = (struct tcphdr *)(skb->data + ip_hdrlen(skb));
-               baseoff = ip_hdrlen(skb) + th->doff * 4;
+               th = (struct tcphdr *)(skb->data + protoff);
+               baseoff = protoff + th->doff * 4;
                matchoff += dataoff - baseoff;
 
                if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
                                                buffer, buflen, false))
                        return 0;
        } else {
-               baseoff = ip_hdrlen(skb) + sizeof(struct udphdr);
+               baseoff = protoff + sizeof(struct udphdr);
                matchoff += dataoff - baseoff;
 
                if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
        return 1;
 }
 
+static int sip_sprintf_addr(const struct nf_conn *ct, char *buffer,
+                           const union nf_inet_addr *addr, bool delim)
+{
+       if (nf_ct_l3num(ct) == NFPROTO_IPV4)
+               return sprintf(buffer, "%pI4", &addr->ip);
+       else {
+               if (delim)
+                       return sprintf(buffer, "[%pI6c]", &addr->ip6);
+               else
+                       return sprintf(buffer, "%pI6c", &addr->ip6);
+       }
+}
+
+static int sip_sprintf_addr_port(const struct nf_conn *ct, char *buffer,
+                                const union nf_inet_addr *addr, u16 port)
+{
+       if (nf_ct_l3num(ct) == NFPROTO_IPV4)
+               return sprintf(buffer, "%pI4:%u", &addr->ip, port);
+       else
+               return sprintf(buffer, "[%pI6c]:%u", &addr->ip6, port);
+}
+
 static int map_addr(struct sk_buff *skb, unsigned int protoff,
                    unsigned int dataoff,
                    const char **dptr, unsigned int *datalen,
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-       char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+       char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
        unsigned int buflen;
-       __be32 newaddr;
+       union nf_inet_addr newaddr;
        __be16 newport;
 
-       if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip &&
+       if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) &&
            ct->tuplehash[dir].tuple.src.u.udp.port == port) {
-               newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
+               newaddr = ct->tuplehash[!dir].tuple.dst.u3;
                newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
-       } else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
+       } else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) &&
                   ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
-               newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
+               newaddr = ct->tuplehash[!dir].tuple.src.u3;
                newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
        } else
                return 1;
 
-       if (newaddr == addr->ip && newport == port)
+       if (nf_inet_addr_cmp(&newaddr, addr) && newport == port)
                return 1;
 
-       buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport));
-
+       buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, ntohs(newport));
        return mangle_packet(skb, protoff, dataoff, dptr, datalen,
                             matchoff, matchlen, buffer, buflen);
 }
                        matchoff, matchlen, &addr, port);
 }
 
-static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int protoff,
+static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
                               unsigned int dataoff,
                               const char **dptr, unsigned int *datalen)
 {
                                    hdr, NULL, &matchoff, &matchlen,
                                    &addr, &port) > 0) {
                unsigned int olen, matchend, poff, plen, buflen, n;
-               char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+               char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
 
                /* We're only interested in headers related to this
                 * connection */
                if (request) {
-                       if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip ||
+                       if (!nf_inet_addr_cmp(&addr,
+                                       &ct->tuplehash[dir].tuple.src.u3) ||
                            port != ct->tuplehash[dir].tuple.src.u.udp.port)
                                goto next;
                } else {
-                       if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip ||
+                       if (!nf_inet_addr_cmp(&addr,
+                                       &ct->tuplehash[dir].tuple.dst.u3) ||
                            port != ct->tuplehash[dir].tuple.dst.u.udp.port)
                                goto next;
                }
                if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
                                               "maddr=", &poff, &plen,
                                               &addr, true) > 0 &&
-                   addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
-                   addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
-                       buflen = sprintf(buffer, "%pI4",
-                                       &ct->tuplehash[!dir].tuple.dst.u3.ip);
+                   nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3) &&
+                   !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3)) {
+                       buflen = sip_sprintf_addr(ct, buffer,
+                                       &ct->tuplehash[!dir].tuple.dst.u3,
+                                       true);
                        if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
                                           poff, plen, buffer, buflen))
                                return NF_DROP;
                if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
                                               "received=", &poff, &plen,
                                               &addr, false) > 0 &&
-                   addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
-                   addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
-                       buflen = sprintf(buffer, "%pI4",
-                                       &ct->tuplehash[!dir].tuple.src.u3.ip);
+                   nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.dst.u3) &&
+                   !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.src.u3)) {
+                       buflen = sip_sprintf_addr(ct, buffer,
+                                       &ct->tuplehash[!dir].tuple.src.u3,
+                                       false);
                        if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
                                           poff, plen, buffer, buflen))
                                return NF_DROP;
        return NF_ACCEPT;
 }
 
-static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off)
+static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
+                                 s16 off)
 {
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0)
                return;
 
-       th = (struct tcphdr *)(skb->data + ip_hdrlen(skb));
+       th = (struct tcphdr *)(skb->data + protoff);
        nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off);
 }
 
 /* Handles expected signalling connections and media streams */
-static void ip_nat_sip_expected(struct nf_conn *ct,
+static void nf_nat_sip_expected(struct nf_conn *ct,
                                struct nf_conntrack_expect *exp)
 {
        struct nf_nat_range range;
 
        /* Change src to where master sends to, but only if the connection
         * actually came from the same source. */
-       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip ==
-           ct->master->tuplehash[exp->dir].tuple.src.u3.ip) {
+       if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
+                            &ct->master->tuplehash[exp->dir].tuple.src.u3)) {
                range.flags = NF_NAT_RANGE_MAP_IPS;
                range.min_addr = range.max_addr
                        = ct->master->tuplehash[!exp->dir].tuple.dst.u3;
        }
 }
 
-static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
+static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
                                      unsigned int dataoff,
                                      const char **dptr, unsigned int *datalen,
                                      struct nf_conntrack_expect *exp,
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-       __be32 newip;
+       union nf_inet_addr newaddr;
        u_int16_t port;
-       char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+       char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
        unsigned int buflen;
 
        /* Connection will come from reply */
-       if (ct->tuplehash[dir].tuple.src.u3.ip == ct->tuplehash[!dir].tuple.dst.u3.ip)
-               newip = exp->tuple.dst.u3.ip;
+       if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
+                            &ct->tuplehash[!dir].tuple.dst.u3))
+               newaddr = exp->tuple.dst.u3;
        else
-               newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+               newaddr = ct->tuplehash[!dir].tuple.dst.u3;
 
        /* If the signalling port matches the connection's source port in the
         * original direction, try to use the destination port in the opposite
                port = ntohs(exp->tuple.dst.u.udp.port);
 
        exp->saved_addr = exp->tuple.dst.u3;
-       exp->tuple.dst.u3.ip = newip;
+       exp->tuple.dst.u3 = newaddr;
        exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
        exp->dir = !dir;
-       exp->expectfn = ip_nat_sip_expected;
+       exp->expectfn = nf_nat_sip_expected;
 
        for (; port != 0; port++) {
                int ret;
        if (port == 0)
                return NF_DROP;
 
-       if (exp->tuple.dst.u3.ip != exp->saved_addr.ip ||
+       if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) ||
            exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
-               buflen = sprintf(buffer, "%pI4:%u", &newip, port);
+               buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port);
                if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
                                   matchoff, matchlen, buffer, buflen))
                        goto err;
                             matchoff, matchlen, buffer, buflen) ? 0 : -EINVAL;
 }
 
-static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int protoff,
+static unsigned int nf_nat_sdp_addr(struct sk_buff *skb, unsigned int protoff,
                                    unsigned int dataoff,
                                    const char **dptr, unsigned int *datalen,
                                    unsigned int sdpoff,
                                    enum sdp_header_types term,
                                    const union nf_inet_addr *addr)
 {
-       char buffer[sizeof("nnn.nnn.nnn.nnn")];
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+       char buffer[INET6_ADDRSTRLEN];
        unsigned int buflen;
 
-       buflen = sprintf(buffer, "%pI4", &addr->ip);
+       buflen = sip_sprintf_addr(ct, buffer, addr, false);
        if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen,
                              sdpoff, type, term, buffer, buflen))
                return 0;
        return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
 }
 
-static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int protoff,
+static unsigned int nf_nat_sdp_port(struct sk_buff *skb, unsigned int protoff,
                                    unsigned int dataoff,
                                    const char **dptr, unsigned int *datalen,
                                    unsigned int matchoff,
        return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
 }
 
-static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int protoff,
+static unsigned int nf_nat_sdp_session(struct sk_buff *skb, unsigned int protoff,
                                       unsigned int dataoff,
                                       const char **dptr, unsigned int *datalen,
                                       unsigned int sdpoff,
                                       const union nf_inet_addr *addr)
 {
-       char buffer[sizeof("nnn.nnn.nnn.nnn")];
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+       char buffer[INET6_ADDRSTRLEN];
        unsigned int buflen;
 
        /* Mangle session description owner and contact addresses */
-       buflen = sprintf(buffer, "%pI4", &addr->ip);
+       buflen = sip_sprintf_addr(ct, buffer, addr, false);
        if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
-                              SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
-                              buffer, buflen))
+                             SDP_HDR_OWNER, SDP_HDR_MEDIA, buffer, buflen))
                return 0;
 
        switch (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
-                                 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
+                                 SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
                                  buffer, buflen)) {
        case 0:
        /*
 
 /* 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_media(struct sk_buff *skb, unsigned int protoff,
+static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
                                     unsigned int dataoff,
                                     const char **dptr, unsigned int *datalen,
                                     struct nf_conntrack_expect *rtp_exp,
        u_int16_t port;
 
        /* Connection will come from reply */
-       if (ct->tuplehash[dir].tuple.src.u3.ip ==
-           ct->tuplehash[!dir].tuple.dst.u3.ip)
-               rtp_addr->ip = rtp_exp->tuple.dst.u3.ip;
+       if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
+                            &ct->tuplehash[!dir].tuple.dst.u3))
+               *rtp_addr = rtp_exp->tuple.dst.u3;
        else
-               rtp_addr->ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+               *rtp_addr = ct->tuplehash[!dir].tuple.dst.u3;
 
        rtp_exp->saved_addr = rtp_exp->tuple.dst.u3;
-       rtp_exp->tuple.dst.u3.ip = rtp_addr->ip;
+       rtp_exp->tuple.dst.u3 = *rtp_addr;
        rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
        rtp_exp->dir = !dir;
-       rtp_exp->expectfn = ip_nat_sip_expected;
+       rtp_exp->expectfn = nf_nat_sip_expected;
 
        rtcp_exp->saved_addr = rtcp_exp->tuple.dst.u3;
-       rtcp_exp->tuple.dst.u3.ip = rtp_addr->ip;
+       rtcp_exp->tuple.dst.u3 = *rtp_addr;
        rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
        rtcp_exp->dir = !dir;
-       rtcp_exp->expectfn = ip_nat_sip_expected;
+       rtcp_exp->expectfn = nf_nat_sip_expected;
 
        /* Try to get same pair of ports: if not, try to change them. */
        for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
 
        /* Update media port. */
        if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
-           !ip_nat_sdp_port(skb, protoff, dataoff, dptr, datalen,
+           !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen,
                             mediaoff, medialen, port))
                goto err2;
 
 }
 
 static struct nf_ct_helper_expectfn sip_nat = {
-        .name           = "sip",
-        .expectfn       = ip_nat_sip_expected,
+       .name           = "sip",
+       .expectfn       = nf_nat_sip_expected,
 };
 
 static void __exit nf_nat_sip_fini(void)
        BUG_ON(nf_nat_sdp_port_hook != NULL);
        BUG_ON(nf_nat_sdp_session_hook != NULL);
        BUG_ON(nf_nat_sdp_media_hook != NULL);
-       RCU_INIT_POINTER(nf_nat_sip_hook, ip_nat_sip);
-       RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust);
-       RCU_INIT_POINTER(nf_nat_sip_expect_hook, ip_nat_sip_expect);
-       RCU_INIT_POINTER(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
-       RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port);
-       RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session);
-       RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media);
+       RCU_INIT_POINTER(nf_nat_sip_hook, nf_nat_sip);
+       RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, nf_nat_sip_seq_adjust);
+       RCU_INIT_POINTER(nf_nat_sip_expect_hook, nf_nat_sip_expect);
+       RCU_INIT_POINTER(nf_nat_sdp_addr_hook, nf_nat_sdp_addr);
+       RCU_INIT_POINTER(nf_nat_sdp_port_hook, nf_nat_sdp_port);
+       RCU_INIT_POINTER(nf_nat_sdp_session_hook, nf_nat_sdp_session);
+       RCU_INIT_POINTER(nf_nat_sdp_media_hook, nf_nat_sdp_media);
        nf_ct_helper_expectfn_register(&sip_nat);
        return 0;
 }