#include <linux/timer.h>
 
 #include <net/checksum.h>
+#include <linux/netfilter.h>           /* for union nf_inet_addr */
+#include <linux/ipv6.h>                        /* for struct ipv6hdr */
+#include <net/ipv6.h>                  /* for ipv6_addr_copy */
 
 #ifdef CONFIG_IP_VS_DEBUG
 #include <linux/net.h>
        struct list_head        c_list;         /* hashed list heads */
 
        /* Protocol, addresses and port numbers */
-       __be32                   caddr;          /* client address */
-       __be32                   vaddr;          /* virtual address */
-       __be32                   daddr;          /* destination address */
+       u16                      af;            /* address family */
+       union nf_inet_addr       caddr;          /* client address */
+       union nf_inet_addr       vaddr;          /* virtual address */
+       union nf_inet_addr       daddr;          /* destination address */
        __be16                   cport;
        __be16                   vport;
        __be16                   dport;
        atomic_t                refcnt;   /* reference counter */
        atomic_t                usecnt;   /* use counter */
 
+       u16                     af;       /* address family */
        __u16                   protocol; /* which protocol (TCP/UDP) */
-       __be32                  addr;     /* IP address for virtual service */
+       union nf_inet_addr      addr;     /* IP address for virtual service */
        __be16                  port;     /* port number for the service */
        __u32                   fwmark;   /* firewall mark of the service */
        unsigned                flags;    /* service status flags */
        struct list_head        n_list;   /* for the dests in the service */
        struct list_head        d_list;   /* for table with all the dests */
 
-       __be32                  addr;           /* IP address of the server */
+       u16                     af;             /* address family */
+       union nf_inet_addr      addr;           /* IP address of the server */
        __be16                  port;           /* port number of the server */
        volatile unsigned       flags;          /* dest status flags */
        atomic_t                conn_flags;     /* flags to copy to conn */
        /* for virtual service */
        struct ip_vs_service    *svc;           /* service it belongs to */
        __u16                   protocol;       /* which protocol (TCP/UDP) */
-       __be32                  vaddr;          /* virtual IP address */
+       union nf_inet_addr      vaddr;          /* virtual IP address */
        __be16                  vport;          /* virtual port number */
        __u32                   vfwmark;        /* firewall mark of service */
 };
 
        int ret;
 
        /* Hash by protocol, client address and port */
-       hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport);
+       hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr.ip, cp->cport);
 
        ct_write_lock(hash);
 
        int ret;
 
        /* unhash it and decrease its reference counter */
-       hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport);
+       hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr.ip, cp->cport);
 
        ct_write_lock(hash);
 
        ct_read_lock(hash);
 
        list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-               if (s_addr==cp->caddr && s_port==cp->cport &&
-                   d_port==cp->vport && d_addr==cp->vaddr &&
+               if (s_addr == cp->caddr.ip && s_port == cp->cport &&
+                   d_port == cp->vport && d_addr == cp->vaddr.ip &&
                    ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
-                   protocol==cp->protocol) {
+                   protocol == cp->protocol) {
                        /* HIT */
                        atomic_inc(&cp->refcnt);
                        ct_read_unlock(hash);
        ct_read_lock(hash);
 
        list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-               if (s_addr==cp->caddr && s_port==cp->cport &&
-                   d_port==cp->vport && d_addr==cp->vaddr &&
+               if (s_addr == cp->caddr.ip && s_port == cp->cport &&
+                   d_port == cp->vport && d_addr == cp->vaddr.ip &&
                    cp->flags & IP_VS_CONN_F_TEMPLATE &&
-                   protocol==cp->protocol) {
+                   protocol == cp->protocol) {
                        /* HIT */
                        atomic_inc(&cp->refcnt);
                        goto out;
        ct_read_lock(hash);
 
        list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-               if (d_addr == cp->caddr && d_port == cp->cport &&
-                   s_port == cp->dport && s_addr == cp->daddr &&
+               if (d_addr == cp->caddr.ip && d_port == cp->cport &&
+                   s_port == cp->dport && s_addr == cp->daddr.ip &&
                    protocol == cp->protocol) {
                        /* HIT */
                        atomic_inc(&cp->refcnt);
                  "d:%u.%u.%u.%u:%d fwd:%c s:%u conn->flags:%X conn->refcnt:%d "
                  "dest->refcnt:%d\n",
                  ip_vs_proto_name(cp->protocol),
-                 NIPQUAD(cp->caddr), ntohs(cp->cport),
-                 NIPQUAD(cp->vaddr), ntohs(cp->vport),
-                 NIPQUAD(cp->daddr), ntohs(cp->dport),
+                 NIPQUAD(cp->caddr.ip), ntohs(cp->cport),
+                 NIPQUAD(cp->vaddr.ip), ntohs(cp->vport),
+                 NIPQUAD(cp->daddr.ip), ntohs(cp->dport),
                  ip_vs_fwd_tag(cp), cp->state,
                  cp->flags, atomic_read(&cp->refcnt),
                  atomic_read(&dest->refcnt));
        struct ip_vs_dest *dest;
 
        if ((cp) && (!cp->dest)) {
-               dest = ip_vs_find_dest(cp->daddr, cp->dport,
-                                      cp->vaddr, cp->vport, cp->protocol);
+               dest = ip_vs_find_dest(cp->daddr.ip, cp->dport,
+                                      cp->vaddr.ip, cp->vport, cp->protocol);
                ip_vs_bind_dest(cp, dest);
                return dest;
        } else
                  "d:%u.%u.%u.%u:%d fwd:%c s:%u conn->flags:%X conn->refcnt:%d "
                  "dest->refcnt:%d\n",
                  ip_vs_proto_name(cp->protocol),
-                 NIPQUAD(cp->caddr), ntohs(cp->cport),
-                 NIPQUAD(cp->vaddr), ntohs(cp->vport),
-                 NIPQUAD(cp->daddr), ntohs(cp->dport),
+                 NIPQUAD(cp->caddr.ip), ntohs(cp->cport),
+                 NIPQUAD(cp->vaddr.ip), ntohs(cp->vport),
+                 NIPQUAD(cp->daddr.ip), ntohs(cp->dport),
                  ip_vs_fwd_tag(cp), cp->state,
                  cp->flags, atomic_read(&cp->refcnt),
                  atomic_read(&dest->refcnt));
                          "protocol %s s:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d "
                          "-> d:%u.%u.%u.%u:%d\n",
                          ip_vs_proto_name(ct->protocol),
-                         NIPQUAD(ct->caddr), ntohs(ct->cport),
-                         NIPQUAD(ct->vaddr), ntohs(ct->vport),
-                         NIPQUAD(ct->daddr), ntohs(ct->dport));
+                         NIPQUAD(ct->caddr.ip), ntohs(ct->cport),
+                         NIPQUAD(ct->vaddr.ip), ntohs(ct->vport),
+                         NIPQUAD(ct->daddr.ip), ntohs(ct->dport));
 
                /*
                 * Invalidate the connection template
        INIT_LIST_HEAD(&cp->c_list);
        setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
        cp->protocol       = proto;
-       cp->caddr          = caddr;
+       cp->caddr.ip       = caddr;
        cp->cport          = cport;
-       cp->vaddr          = vaddr;
+       cp->vaddr.ip       = vaddr;
        cp->vport          = vport;
-       cp->daddr          = daddr;
+       cp->daddr.ip       = daddr;
        cp->dport          = dport;
        cp->flags          = flags;
        spin_lock_init(&cp->lock);
                seq_printf(seq,
                        "%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu\n",
                                ip_vs_proto_name(cp->protocol),
-                               ntohl(cp->caddr), ntohs(cp->cport),
-                               ntohl(cp->vaddr), ntohs(cp->vport),
-                               ntohl(cp->daddr), ntohs(cp->dport),
+                               ntohl(cp->caddr.ip), ntohs(cp->cport),
+                               ntohl(cp->vaddr.ip), ntohs(cp->vport),
+                               ntohl(cp->daddr.ip), ntohs(cp->dport),
                                ip_vs_state_name(cp->protocol, cp->state),
                                (cp->timer.expires-jiffies)/HZ);
        }
                seq_printf(seq,
                        "%-3s %08X %04X %08X %04X %08X %04X %-11s %-6s %7lu\n",
                                ip_vs_proto_name(cp->protocol),
-                               ntohl(cp->caddr), ntohs(cp->cport),
-                               ntohl(cp->vaddr), ntohs(cp->vport),
-                               ntohl(cp->daddr), ntohs(cp->dport),
+                               ntohl(cp->caddr.ip), ntohs(cp->cport),
+                               ntohl(cp->vaddr.ip), ntohs(cp->vport),
+                               ntohl(cp->daddr.ip), ntohs(cp->dport),
                                ip_vs_state_name(cp->protocol, cp->state),
                                ip_vs_origin_name(cp->flags),
                                (cp->timer.expires-jiffies)/HZ);
 
                                                    snet, 0,
                                                    iph->daddr,
                                                    ports[1],
-                                                   dest->addr, dest->port,
+                                                   dest->addr.ip, dest->port,
                                                    IP_VS_CONN_F_TEMPLATE,
                                                    dest);
                        else
                                ct = ip_vs_conn_new(iph->protocol,
                                                    snet, 0,
                                                    iph->daddr, 0,
-                                                   dest->addr, 0,
+                                                   dest->addr.ip, 0,
                                                    IP_VS_CONN_F_TEMPLATE,
                                                    dest);
                        if (ct == NULL)
                                ct = ip_vs_conn_new(IPPROTO_IP,
                                                    snet, 0,
                                                    htonl(svc->fwmark), 0,
-                                                   dest->addr, 0,
+                                                   dest->addr.ip, 0,
                                                    IP_VS_CONN_F_TEMPLATE,
                                                    dest);
                        else
                                ct = ip_vs_conn_new(iph->protocol,
                                                    snet, 0,
                                                    iph->daddr, 0,
-                                                   dest->addr, 0,
+                                                   dest->addr.ip, 0,
                                                    IP_VS_CONN_F_TEMPLATE,
                                                    dest);
                        if (ct == NULL)
        cp = ip_vs_conn_new(iph->protocol,
                            iph->saddr, ports[0],
                            iph->daddr, ports[1],
-                           dest->addr, dport,
+                           dest->addr.ip, dport,
                            0,
                            dest);
        if (cp == NULL) {
        cp = ip_vs_conn_new(iph->protocol,
                            iph->saddr, pptr[0],
                            iph->daddr, pptr[1],
-                           dest->addr, dest->port?dest->port:pptr[1],
+                           dest->addr.ip, dest->port ? dest->port : pptr[1],
                            0,
                            dest);
        if (cp == NULL)
        IP_VS_DBG(6, "Schedule fwd:%c c:%u.%u.%u.%u:%u v:%u.%u.%u.%u:%u "
                  "d:%u.%u.%u.%u:%u conn->flags:%X conn->refcnt:%d\n",
                  ip_vs_fwd_tag(cp),
-                 NIPQUAD(cp->caddr), ntohs(cp->cport),
-                 NIPQUAD(cp->vaddr), ntohs(cp->vport),
-                 NIPQUAD(cp->daddr), ntohs(cp->dport),
+                 NIPQUAD(cp->caddr.ip), ntohs(cp->cport),
+                 NIPQUAD(cp->vaddr.ip), ntohs(cp->vport),
+                 NIPQUAD(cp->daddr.ip), ntohs(cp->dport),
                  cp->flags, atomic_read(&cp->refcnt));
 
        ip_vs_conn_stats(cp, svc);
        struct iphdr *ciph       = (struct iphdr *)(icmph + 1);
 
        if (inout) {
-               iph->saddr = cp->vaddr;
+               iph->saddr = cp->vaddr.ip;
                ip_send_check(iph);
-               ciph->daddr = cp->vaddr;
+               ciph->daddr = cp->vaddr.ip;
                ip_send_check(ciph);
        } else {
-               iph->daddr = cp->daddr;
+               iph->daddr = cp->daddr.ip;
                ip_send_check(iph);
-               ciph->saddr = cp->daddr;
+               ciph->saddr = cp->daddr.ip;
                ip_send_check(ciph);
        }
 
        /* mangle the packet */
        if (pp->snat_handler && !pp->snat_handler(skb, pp, cp))
                goto drop;
-       ip_hdr(skb)->saddr = cp->vaddr;
+       ip_hdr(skb)->saddr = cp->vaddr.ip;
        ip_send_check(ip_hdr(skb));
 
        /* For policy routing, packets originating from this
 
                /*
                 *  Hash it by <protocol,addr,port> in ip_vs_svc_table
                 */
-               hash = ip_vs_svc_hashkey(svc->protocol, svc->addr, svc->port);
+               hash = ip_vs_svc_hashkey(svc->protocol, svc->addr.ip,
+                                        svc->port);
                list_add(&svc->s_list, &ip_vs_svc_table[hash]);
        } else {
                /*
        hash = ip_vs_svc_hashkey(protocol, vaddr, vport);
 
        list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){
-               if ((svc->addr == vaddr)
+               if ((svc->addr.ip == vaddr)
                    && (svc->port == vport)
                    && (svc->protocol == protocol)) {
                        /* HIT */
         *      Hash by proto,addr,port,
         *      which are the parameters of the real service.
         */
-       hash = ip_vs_rs_hashkey(dest->addr, dest->port);
+       hash = ip_vs_rs_hashkey(dest->addr.ip, dest->port);
        list_add(&dest->d_list, &ip_vs_rtable[hash]);
 
        return 1;
 
        read_lock(&__ip_vs_rs_lock);
        list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) {
-               if ((dest->addr == daddr)
+               if ((dest->addr.ip == daddr)
                    && (dest->port == dport)
                    && ((dest->protocol == protocol) ||
                        dest->vfwmark)) {
         * Find the destination for the given service
         */
        list_for_each_entry(dest, &svc->destinations, n_list) {
-               if ((dest->addr == daddr) && (dest->port == dport)) {
+               if ((dest->addr.ip == daddr) && (dest->port == dport)) {
                        /* HIT */
                        return dest;
                }
                IP_VS_DBG(3, "Destination %u/%u.%u.%u.%u:%u still in trash, "
                          "dest->refcnt=%d\n",
                          dest->vfwmark,
-                         NIPQUAD(dest->addr), ntohs(dest->port),
+                         NIPQUAD(dest->addr.ip), ntohs(dest->port),
                          atomic_read(&dest->refcnt));
-               if (dest->addr == daddr &&
+               if (dest->addr.ip == daddr &&
                    dest->port == dport &&
                    dest->vfwmark == svc->fwmark &&
                    dest->protocol == svc->protocol &&
                    (svc->fwmark ||
-                    (dest->vaddr == svc->addr &&
+                    (dest->vaddr.ip == svc->addr.ip &&
                      dest->vport == svc->port))) {
                        /* HIT */
                        return dest;
                        IP_VS_DBG(3, "Removing destination %u/%u.%u.%u.%u:%u "
                                  "from trash\n",
                                  dest->vfwmark,
-                                 NIPQUAD(dest->addr), ntohs(dest->port));
+                                 NIPQUAD(dest->addr.ip), ntohs(dest->port));
                        list_del(&dest->n_list);
                        ip_vs_dst_reset(dest);
                        __ip_vs_unbind_svc(dest);
        }
 
        dest->protocol = svc->protocol;
-       dest->vaddr = svc->addr;
+       dest->vaddr.ip = svc->addr.ip;
        dest->vport = svc->port;
        dest->vfwmark = svc->fwmark;
-       dest->addr = udest->addr;
+       dest->addr.ip = udest->addr;
        dest->port = udest->port;
 
        atomic_set(&dest->activeconns, 0);
                          NIPQUAD(daddr), ntohs(dport),
                          atomic_read(&dest->refcnt),
                          dest->vfwmark,
-                         NIPQUAD(dest->vaddr),
+                         NIPQUAD(dest->vaddr.ip),
                          ntohs(dest->vport));
                __ip_vs_update_dest(svc, dest, udest);
 
        } else {
                IP_VS_DBG(3, "Moving dest %u.%u.%u.%u:%u into trash, "
                          "dest->refcnt=%d\n",
-                         NIPQUAD(dest->addr), ntohs(dest->port),
+                         NIPQUAD(dest->addr.ip), ntohs(dest->port),
                          atomic_read(&dest->refcnt));
                list_add(&dest->n_list, &ip_vs_dest_trash);
                atomic_inc(&dest->refcnt);
        atomic_set(&svc->refcnt, 0);
 
        svc->protocol = u->protocol;
-       svc->addr = u->addr;
+       svc->addr.ip = u->addr;
        svc->port = u->port;
        svc->fwmark = u->fwmark;
        svc->flags = u->flags;
                if (iter->table == ip_vs_svc_table)
                        seq_printf(seq, "%s  %08X:%04X %s ",
                                   ip_vs_proto_name(svc->protocol),
-                                  ntohl(svc->addr),
+                                  ntohl(svc->addr.ip),
                                   ntohs(svc->port),
                                   svc->scheduler->name);
                else
                list_for_each_entry(dest, &svc->destinations, n_list) {
                        seq_printf(seq,
                                   "  -> %08X:%04X      %-7s %-6d %-10d %-10d\n",
-                                  ntohl(dest->addr), ntohs(dest->port),
+                                  ntohl(dest->addr.ip), ntohs(dest->port),
                                   ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
                                   atomic_read(&dest->weight),
                                   atomic_read(&dest->activeconns),
 ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
 {
        dst->protocol = src->protocol;
-       dst->addr = src->addr;
+       dst->addr = src->addr.ip;
        dst->port = src->port;
        dst->fwmark = src->fwmark;
        strlcpy(dst->sched_name, src->scheduler->name, sizeof(dst->sched_name));
                        if (count >= get->num_dests)
                                break;
 
-                       entry.addr = dest->addr;
+                       entry.addr = dest->addr.ip;
                        entry.port = dest->port;
                        entry.conn_flags = atomic_read(&dest->conn_flags);
                        entry.weight = atomic_read(&dest->weight);
 
        IP_VS_DBG(6, "DH: destination IP address %u.%u.%u.%u "
                  "--> server %u.%u.%u.%u:%d\n",
                  NIPQUAD(iph->daddr),
-                 NIPQUAD(dest->addr),
+                 NIPQUAD(dest->addr.ip),
                  ntohs(dest->port));
 
        return dest;
 
 
                IP_VS_DBG(7, "PASV response (%u.%u.%u.%u:%d) -> "
                          "%u.%u.%u.%u:%d detected\n",
-                         NIPQUAD(from), ntohs(port), NIPQUAD(cp->caddr), 0);
+                         NIPQUAD(from), ntohs(port), NIPQUAD(cp->caddr.ip), 0);
 
                /*
                 * Now update or create an connection entry for it
                 */
                n_cp = ip_vs_conn_out_get(iph->protocol, from, port,
-                                         cp->caddr, 0);
+                                         cp->caddr.ip, 0);
                if (!n_cp) {
                        n_cp = ip_vs_conn_new(IPPROTO_TCP,
-                                             cp->caddr, 0,
-                                             cp->vaddr, port,
+                                             cp->caddr.ip, 0,
+                                             cp->vaddr.ip, port,
                                              from, port,
                                              IP_VS_CONN_F_NO_CPORT,
                                              cp->dest);
                /*
                 * Replace the old passive address with the new one
                 */
-               from = n_cp->vaddr;
+               from = n_cp->vaddr.ip;
                port = n_cp->vport;
                sprintf(buf,"%d,%d,%d,%d,%d,%d", NIPQUAD(from),
                        (ntohs(port)>>8)&255, ntohs(port)&255);
         */
        IP_VS_DBG(7, "protocol %s %u.%u.%u.%u:%d %u.%u.%u.%u:%d\n",
                  ip_vs_proto_name(iph->protocol),
-                 NIPQUAD(to), ntohs(port), NIPQUAD(cp->vaddr), 0);
+                 NIPQUAD(to), ntohs(port), NIPQUAD(cp->vaddr.ip), 0);
 
        n_cp = ip_vs_conn_in_get(iph->protocol,
                                 to, port,
-                                cp->vaddr, htons(ntohs(cp->vport)-1));
+                                cp->vaddr.ip, htons(ntohs(cp->vport)-1));
        if (!n_cp) {
                n_cp = ip_vs_conn_new(IPPROTO_TCP,
                                      to, port,
-                                     cp->vaddr, htons(ntohs(cp->vport)-1),
-                                     cp->daddr, htons(ntohs(cp->dport)-1),
+                                     cp->vaddr.ip, htons(ntohs(cp->vport)-1),
+                                     cp->daddr.ip, htons(ntohs(cp->dport)-1),
                                      0,
                                      cp->dest);
                if (!n_cp)
 
 
        IP_VS_DBG(6, "LBLC: server %d.%d.%d.%d:%d "
                  "activeconns %d refcnt %d weight %d overhead %d\n",
-                 NIPQUAD(least->addr), ntohs(least->port),
+                 NIPQUAD(least->addr.ip), ntohs(least->port),
                  atomic_read(&least->activeconns),
                  atomic_read(&least->refcnt),
                  atomic_read(&least->weight), loh);
        IP_VS_DBG(6, "LBLC: destination IP address %u.%u.%u.%u "
                  "--> server %u.%u.%u.%u:%d\n",
                  NIPQUAD(iph->daddr),
-                 NIPQUAD(dest->addr),
+                 NIPQUAD(dest->addr.ip),
                  ntohs(dest->port));
 
        return dest;
 
 
        IP_VS_DBG(6, "ip_vs_dest_set_min: server %d.%d.%d.%d:%d "
                  "activeconns %d refcnt %d weight %d overhead %d\n",
-                 NIPQUAD(least->addr), ntohs(least->port),
+                 NIPQUAD(least->addr.ip), ntohs(least->port),
                  atomic_read(&least->activeconns),
                  atomic_read(&least->refcnt),
                  atomic_read(&least->weight), loh);
 
        IP_VS_DBG(6, "ip_vs_dest_set_max: server %d.%d.%d.%d:%d "
                  "activeconns %d refcnt %d weight %d overhead %d\n",
-                 NIPQUAD(most->addr), ntohs(most->port),
+                 NIPQUAD(most->addr.ip), ntohs(most->port),
                  atomic_read(&most->activeconns),
                  atomic_read(&most->refcnt),
                  atomic_read(&most->weight), moh);
 
        IP_VS_DBG(6, "LBLCR: server %d.%d.%d.%d:%d "
                  "activeconns %d refcnt %d weight %d overhead %d\n",
-                 NIPQUAD(least->addr), ntohs(least->port),
+                 NIPQUAD(least->addr.ip), ntohs(least->port),
                  atomic_read(&least->activeconns),
                  atomic_read(&least->refcnt),
                  atomic_read(&least->weight), loh);
        IP_VS_DBG(6, "LBLCR: destination IP address %u.%u.%u.%u "
                  "--> server %u.%u.%u.%u:%d\n",
                  NIPQUAD(iph->daddr),
-                 NIPQUAD(dest->addr),
+                 NIPQUAD(dest->addr.ip),
                  ntohs(dest->port));
 
        return dest;
 
 
        if (least)
        IP_VS_DBG(6, "LC: server %u.%u.%u.%u:%u activeconns %d inactconns %d\n",
-                 NIPQUAD(least->addr), ntohs(least->port),
+                 NIPQUAD(least->addr.ip), ntohs(least->port),
                  atomic_read(&least->activeconns),
                  atomic_read(&least->inactconns));
 
 
   out:
        IP_VS_DBG(6, "NQ: server %u.%u.%u.%u:%u "
                  "activeconns %d refcnt %d weight %d overhead %d\n",
-                 NIPQUAD(least->addr), ntohs(least->port),
+                 NIPQUAD(least->addr.ip), ntohs(least->port),
                  atomic_read(&least->activeconns),
                  atomic_read(&least->refcnt),
                  atomic_read(&least->weight), loh);
 
        /* Adjust TCP checksums */
        if (!cp->app) {
                /* Only port and addr are changed, do fast csum update */
-               tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr,
+               tcp_fast_csum_update(tcph, cp->daddr.ip, cp->vaddr.ip,
                                     cp->dport, cp->vport);
                if (skb->ip_summed == CHECKSUM_COMPLETE)
                        skb->ip_summed = CHECKSUM_NONE;
                /* full checksum calculation */
                tcph->check = 0;
                skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
-               tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
+               tcph->check = csum_tcpudp_magic(cp->vaddr.ip, cp->caddr.ip,
                                                skb->len - tcphoff,
                                                cp->protocol, skb->csum);
                IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
         */
        if (!cp->app) {
                /* Only port and addr are changed, do fast csum update */
-               tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr,
+               tcp_fast_csum_update(tcph, cp->vaddr.ip, cp->daddr.ip,
                                     cp->vport, cp->dport);
                if (skb->ip_summed == CHECKSUM_COMPLETE)
                        skb->ip_summed = CHECKSUM_NONE;
                /* full checksum calculation */
                tcph->check = 0;
                skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
-               tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
+               tcph->check = csum_tcpudp_magic(cp->caddr.ip, cp->daddr.ip,
                                                skb->len - tcphoff,
                                                cp->protocol, skb->csum);
                skb->ip_summed = CHECKSUM_UNNECESSARY;
                          th->fin? 'F' : '.',
                          th->ack? 'A' : '.',
                          th->rst? 'R' : '.',
-                         NIPQUAD(cp->daddr), ntohs(cp->dport),
-                         NIPQUAD(cp->caddr), ntohs(cp->cport),
+                         NIPQUAD(cp->daddr.ip), ntohs(cp->dport),
+                         NIPQUAD(cp->caddr.ip), ntohs(cp->cport),
                          tcp_state_name(cp->state),
                          tcp_state_name(new_state),
                          atomic_read(&cp->refcnt));
                        IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->"
                                  "%u.%u.%u.%u:%u to app %s on port %u\n",
                                  __func__,
-                                 NIPQUAD(cp->caddr), ntohs(cp->cport),
-                                 NIPQUAD(cp->vaddr), ntohs(cp->vport),
+                                 NIPQUAD(cp->caddr.ip), ntohs(cp->cport),
+                                 NIPQUAD(cp->vaddr.ip), ntohs(cp->vport),
                                  inc->name, ntohs(inc->port));
                        cp->app = inc;
                        if (inc->init_conn)
 
         */
        if (!cp->app && (udph->check != 0)) {
                /* Only port and addr are changed, do fast csum update */
-               udp_fast_csum_update(udph, cp->daddr, cp->vaddr,
+               udp_fast_csum_update(udph, cp->daddr.ip, cp->vaddr.ip,
                                     cp->dport, cp->vport);
                if (skb->ip_summed == CHECKSUM_COMPLETE)
                        skb->ip_summed = CHECKSUM_NONE;
                /* full checksum calculation */
                udph->check = 0;
                skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0);
-               udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
+               udph->check = csum_tcpudp_magic(cp->vaddr.ip, cp->caddr.ip,
                                                skb->len - udphoff,
                                                cp->protocol, skb->csum);
                if (udph->check == 0)
         */
        if (!cp->app && (udph->check != 0)) {
                /* Only port and addr are changed, do fast csum update */
-               udp_fast_csum_update(udph, cp->vaddr, cp->daddr,
+               udp_fast_csum_update(udph, cp->vaddr.ip, cp->daddr.ip,
                                     cp->vport, cp->dport);
                if (skb->ip_summed == CHECKSUM_COMPLETE)
                        skb->ip_summed = CHECKSUM_NONE;
                /* full checksum calculation */
                udph->check = 0;
                skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0);
-               udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
+               udph->check = csum_tcpudp_magic(cp->caddr.ip, cp->daddr.ip,
                                                skb->len - udphoff,
                                                cp->protocol, skb->csum);
                if (udph->check == 0)
                        IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->"
                                  "%u.%u.%u.%u:%u to app %s on port %u\n",
                                  __func__,
-                                 NIPQUAD(cp->caddr), ntohs(cp->cport),
-                                 NIPQUAD(cp->vaddr), ntohs(cp->vport),
+                                 NIPQUAD(cp->caddr.ip), ntohs(cp->cport),
+                                 NIPQUAD(cp->vaddr.ip), ntohs(cp->vport),
                                  inc->name, ntohs(inc->port));
                        cp->app = inc;
                        if (inc->init_conn)
 
        write_unlock(&svc->sched_lock);
        IP_VS_DBG(6, "RR: server %u.%u.%u.%u:%u "
                  "activeconns %d refcnt %d weight %d\n",
-                 NIPQUAD(dest->addr), ntohs(dest->port),
+                 NIPQUAD(dest->addr.ip), ntohs(dest->port),
                  atomic_read(&dest->activeconns),
                  atomic_read(&dest->refcnt), atomic_read(&dest->weight));
 
 
 
        IP_VS_DBG(6, "SED: server %u.%u.%u.%u:%u "
                  "activeconns %d refcnt %d weight %d overhead %d\n",
-                 NIPQUAD(least->addr), ntohs(least->port),
+                 NIPQUAD(least->addr.ip), ntohs(least->port),
                  atomic_read(&least->activeconns),
                  atomic_read(&least->refcnt),
                  atomic_read(&least->weight), loh);
 
        IP_VS_DBG(6, "SH: source IP address %u.%u.%u.%u "
                  "--> server %u.%u.%u.%u:%d\n",
                  NIPQUAD(iph->saddr),
-                 NIPQUAD(dest->addr),
+                 NIPQUAD(dest->addr.ip),
                  ntohs(dest->port));
 
        return dest;
 
        s->cport = cp->cport;
        s->vport = cp->vport;
        s->dport = cp->dport;
-       s->caddr = cp->caddr;
-       s->vaddr = cp->vaddr;
-       s->daddr = cp->daddr;
+       s->caddr = cp->caddr.ip;
+       s->vaddr = cp->vaddr.ip;
+       s->daddr = cp->daddr.ip;
        s->flags = htons(cp->flags & ~IP_VS_CONN_F_HASHED);
        s->state = htons(cp->state);
        if (cp->flags & IP_VS_CONN_F_SEQ_MASK) {
 
 
        IP_VS_DBG(6, "WLC: server %u.%u.%u.%u:%u "
                  "activeconns %d refcnt %d weight %d overhead %d\n",
-                 NIPQUAD(least->addr), ntohs(least->port),
+                 NIPQUAD(least->addr.ip), ntohs(least->port),
                  atomic_read(&least->activeconns),
                  atomic_read(&least->refcnt),
                  atomic_read(&least->weight), loh);
 
 
        IP_VS_DBG(6, "WRR: server %u.%u.%u.%u:%u "
                  "activeconns %d refcnt %d weight %d\n",
-                 NIPQUAD(dest->addr), ntohs(dest->port),
+                 NIPQUAD(dest->addr.ip), ntohs(dest->port),
                  atomic_read(&dest->activeconns),
                  atomic_read(&dest->refcnt),
                  atomic_read(&dest->weight));
 
                                .oif = 0,
                                .nl_u = {
                                        .ip4_u = {
-                                               .daddr = dest->addr,
+                                               .daddr = dest->addr.ip,
                                                .saddr = 0,
                                                .tos = rtos, } },
                        };
                                spin_unlock(&dest->dst_lock);
                                IP_VS_DBG_RL("ip_route_output error, "
                                             "dest: %u.%u.%u.%u\n",
-                                            NIPQUAD(dest->addr));
+                                            NIPQUAD(dest->addr.ip));
                                return NULL;
                        }
                        __ip_vs_dst_set(dest, rtos, dst_clone(&rt->u.dst));
                        IP_VS_DBG(10, "new dst %u.%u.%u.%u, refcnt=%d, rtos=%X\n",
-                                 NIPQUAD(dest->addr),
+                                 NIPQUAD(dest->addr.ip),
                                  atomic_read(&rt->u.dst.__refcnt), rtos);
                }
                spin_unlock(&dest->dst_lock);
                        .oif = 0,
                        .nl_u = {
                                .ip4_u = {
-                                       .daddr = cp->daddr,
+                                       .daddr = cp->daddr.ip,
                                        .saddr = 0,
                                        .tos = rtos, } },
                };
 
                if (ip_route_output_key(&init_net, &rt, &fl)) {
                        IP_VS_DBG_RL("ip_route_output error, dest: "
-                                    "%u.%u.%u.%u\n", NIPQUAD(cp->daddr));
+                                    "%u.%u.%u.%u\n", NIPQUAD(cp->daddr.ip));
                        return NULL;
                }
        }
        /* mangle the packet */
        if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
                goto tx_error;
-       ip_hdr(skb)->daddr = cp->daddr;
+       ip_hdr(skb)->daddr = cp->daddr.ip;
        ip_send_check(ip_hdr(skb));
 
        IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");