dest->u_threshold = udest->u_threshold;
        dest->l_threshold = udest->l_threshold;
 
+       dest->af = udest->af;
+
        spin_lock_bh(&dest->dst_lock);
        __ip_vs_dst_cache_reset(dest);
        spin_unlock_bh(&dest->dst_lock);
 
        EnterFunction(2);
 
+       /* Temporary for consistency */
+       if (udest->af != svc->af)
+               return -EINVAL;
+
 #ifdef CONFIG_IP_VS_IPV6
-       if (svc->af == AF_INET6) {
+       if (udest->af == AF_INET6) {
                atype = ipv6_addr_type(&udest->addr.in6);
                if ((!(atype & IPV6_ADDR_UNICAST) ||
                        atype & IPV6_ADDR_LINKLOCAL) &&
                u64_stats_init(&ip_vs_dest_stats->syncp);
        }
 
-       dest->af = svc->af;
+       dest->af = udest->af;
        dest->protocol = svc->protocol;
        dest->vaddr = svc->addr;
        dest->vport = svc->port;
        dest->vfwmark = svc->fwmark;
-       ip_vs_addr_copy(svc->af, &dest->addr, &udest->addr);
+       ip_vs_addr_copy(udest->af, &dest->addr, &udest->addr);
        dest->port = udest->port;
 
        atomic_set(&dest->activeconns, 0);
                return -ERANGE;
        }
 
-       ip_vs_addr_copy(svc->af, &daddr, &udest->addr);
+       ip_vs_addr_copy(udest->af, &daddr, &udest->addr);
 
        /* We use function that requires RCU lock */
        rcu_read_lock();
        if (dest != NULL) {
                IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, "
                              "dest->refcnt=%d, service %u/%s:%u\n",
-                             IP_VS_DBG_ADDR(svc->af, &daddr), ntohs(dport),
+                             IP_VS_DBG_ADDR(udest->af, &daddr), ntohs(dport),
                              atomic_read(&dest->refcnt),
                              dest->vfwmark,
                              IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
                return -ERANGE;
        }
 
-       ip_vs_addr_copy(svc->af, &daddr, &udest->addr);
+       ip_vs_addr_copy(udest->af, &daddr, &udest->addr);
 
        /* We use function that requires RCU lock */
        rcu_read_lock();
        udest->weight           = udest_compat->weight;
        udest->u_threshold      = udest_compat->u_threshold;
        udest->l_threshold      = udest_compat->l_threshold;
+       udest->af               = AF_INET;
 }
 
 static int
                        if (count >= get->num_dests)
                                break;
 
+                       /* Cannot expose heterogeneous members via sockopt
+                        * interface
+                        */
+                       if (dest->af != svc->af)
+                               continue;
+
                        entry.addr = dest->addr.ip;
                        entry.port = dest->port;
                        entry.conn_flags = atomic_read(&dest->conn_flags);
        [IPVS_DEST_ATTR_INACT_CONNS]    = { .type = NLA_U32 },
        [IPVS_DEST_ATTR_PERSIST_CONNS]  = { .type = NLA_U32 },
        [IPVS_DEST_ATTR_STATS]          = { .type = NLA_NESTED },
+       [IPVS_DEST_ATTR_ADDR_FAMILY]    = { .type = NLA_U16 },
 };
 
 static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,
            nla_put_u32(skb, IPVS_DEST_ATTR_INACT_CONNS,
                        atomic_read(&dest->inactconns)) ||
            nla_put_u32(skb, IPVS_DEST_ATTR_PERSIST_CONNS,
-                       atomic_read(&dest->persistconns)))
+                       atomic_read(&dest->persistconns)) ||
+           nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))
                goto nla_put_failure;
        if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats))
                goto nla_put_failure;
 {
        struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1];
        struct nlattr *nla_addr, *nla_port;
+       struct nlattr *nla_addr_family;
 
        /* Parse mandatory identifying destination fields first */
        if (nla == NULL ||
 
        nla_addr        = attrs[IPVS_DEST_ATTR_ADDR];
        nla_port        = attrs[IPVS_DEST_ATTR_PORT];
+       nla_addr_family = attrs[IPVS_DEST_ATTR_ADDR_FAMILY];
 
        if (!(nla_addr && nla_port))
                return -EINVAL;
        nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr));
        udest->port = nla_get_be16(nla_port);
 
+       if (nla_addr_family)
+               udest->af = nla_get_u16(nla_addr_family);
+       else
+               udest->af = 0;
+
        /* If a full entry was requested, check for the additional fields */
        if (full_entry) {
                struct nlattr *nla_fwd, *nla_weight, *nla_u_thresh,
                                            need_full_dest);
                if (ret)
                        goto out;
+
+               /* Old protocols did not allow the user to specify address
+                * family, so we set it to zero instead.  We also didn't
+                * allow heterogeneous pools in the old code, so it's safe
+                * to assume that this will have the same address family as
+                * the service.
+                */
+               if (udest.af == 0)
+                       udest.af = svc->af;
        }
 
        switch (cmd) {