ipvs: Pass ipvs not net to __ip_vs_get_service_entries
[deliverable/linux.git] / net / netfilter / ipvs / ip_vs_ctl.c
index 24c554201a766d175ed90359b6b78617acd37c64..05f7e1d147381b082610b981fce4caec5553782c 100644 (file)
@@ -263,7 +263,7 @@ static struct hlist_head ip_vs_svc_fwm_table[IP_VS_SVC_TAB_SIZE];
  *     Returns hash value for virtual service
  */
 static inline unsigned int
-ip_vs_svc_hashkey(struct net *net, int af, unsigned int proto,
+ip_vs_svc_hashkey(struct netns_ipvs *ipvs, int af, unsigned int proto,
                  const union nf_inet_addr *addr, __be16 port)
 {
        register unsigned int porth = ntohs(port);
@@ -276,7 +276,7 @@ ip_vs_svc_hashkey(struct net *net, int af, unsigned int proto,
                            addr->ip6[2]^addr->ip6[3];
 #endif
        ahash = ntohl(addr_fold);
-       ahash ^= ((size_t) net >> 8);
+       ahash ^= ((size_t) ipvs >> 8);
 
        return (proto ^ ahash ^ (porth >> IP_VS_SVC_TAB_BITS) ^ porth) &
               IP_VS_SVC_TAB_MASK;
@@ -285,9 +285,9 @@ ip_vs_svc_hashkey(struct net *net, int af, unsigned int proto,
 /*
  *     Returns hash value of fwmark for virtual service lookup
  */
-static inline unsigned int ip_vs_svc_fwm_hashkey(struct net *net, __u32 fwmark)
+static inline unsigned int ip_vs_svc_fwm_hashkey(struct netns_ipvs *ipvs, __u32 fwmark)
 {
-       return (((size_t)net>>8) ^ fwmark) & IP_VS_SVC_TAB_MASK;
+       return (((size_t)ipvs>>8) ^ fwmark) & IP_VS_SVC_TAB_MASK;
 }
 
 /*
@@ -309,14 +309,14 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
                /*
                 *  Hash it by <netns,protocol,addr,port> in ip_vs_svc_table
                 */
-               hash = ip_vs_svc_hashkey(svc->net, svc->af, svc->protocol,
+               hash = ip_vs_svc_hashkey(svc->ipvs, svc->af, svc->protocol,
                                         &svc->addr, svc->port);
                hlist_add_head_rcu(&svc->s_list, &ip_vs_svc_table[hash]);
        } else {
                /*
                 *  Hash it by fwmark in svc_fwm_table
                 */
-               hash = ip_vs_svc_fwm_hashkey(svc->net, svc->fwmark);
+               hash = ip_vs_svc_fwm_hashkey(svc->ipvs, svc->fwmark);
                hlist_add_head_rcu(&svc->f_list, &ip_vs_svc_fwm_table[hash]);
        }
 
@@ -357,21 +357,21 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
  *     Get service by {netns, proto,addr,port} in the service table.
  */
 static inline struct ip_vs_service *
-__ip_vs_service_find(struct net *net, int af, __u16 protocol,
+__ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u16 protocol,
                     const union nf_inet_addr *vaddr, __be16 vport)
 {
        unsigned int hash;
        struct ip_vs_service *svc;
 
        /* Check for "full" addressed entries */
-       hash = ip_vs_svc_hashkey(net, af, protocol, vaddr, vport);
+       hash = ip_vs_svc_hashkey(ipvs, af, protocol, vaddr, vport);
 
        hlist_for_each_entry_rcu(svc, &ip_vs_svc_table[hash], s_list) {
                if ((svc->af == af)
                    && ip_vs_addr_equal(af, &svc->addr, vaddr)
                    && (svc->port == vport)
                    && (svc->protocol == protocol)
-                   && net_eq(svc->net, net)) {
+                   && (svc->ipvs == ipvs)) {
                        /* HIT */
                        return svc;
                }
@@ -385,17 +385,17 @@ __ip_vs_service_find(struct net *net, int af, __u16 protocol,
  *     Get service by {fwmark} in the service table.
  */
 static inline struct ip_vs_service *
-__ip_vs_svc_fwm_find(struct net *net, int af, __u32 fwmark)
+__ip_vs_svc_fwm_find(struct netns_ipvs *ipvs, int af, __u32 fwmark)
 {
        unsigned int hash;
        struct ip_vs_service *svc;
 
        /* Check for fwmark addressed entries */
-       hash = ip_vs_svc_fwm_hashkey(net, fwmark);
+       hash = ip_vs_svc_fwm_hashkey(ipvs, fwmark);
 
        hlist_for_each_entry_rcu(svc, &ip_vs_svc_fwm_table[hash], f_list) {
                if (svc->fwmark == fwmark && svc->af == af
-                   && net_eq(svc->net, net)) {
+                   && (svc->ipvs == ipvs)) {
                        /* HIT */
                        return svc;
                }
@@ -406,17 +406,16 @@ __ip_vs_svc_fwm_find(struct net *net, int af, __u32 fwmark)
 
 /* Find service, called under RCU lock */
 struct ip_vs_service *
-ip_vs_service_find(struct net *net, int af, __u32 fwmark, __u16 protocol,
+ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol,
                   const union nf_inet_addr *vaddr, __be16 vport)
 {
        struct ip_vs_service *svc;
-       struct netns_ipvs *ipvs = net_ipvs(net);
 
        /*
         *      Check the table hashed by fwmark first
         */
        if (fwmark) {
-               svc = __ip_vs_svc_fwm_find(net, af, fwmark);
+               svc = __ip_vs_svc_fwm_find(ipvs, af, fwmark);
                if (svc)
                        goto out;
        }
@@ -425,7 +424,7 @@ ip_vs_service_find(struct net *net, int af, __u32 fwmark, __u16 protocol,
         *      Check the table hashed by <protocol,addr,port>
         *      for "full" addressed entries
         */
-       svc = __ip_vs_service_find(net, af, protocol, vaddr, vport);
+       svc = __ip_vs_service_find(ipvs, af, protocol, vaddr, vport);
 
        if (svc == NULL
            && protocol == IPPROTO_TCP
@@ -435,7 +434,7 @@ ip_vs_service_find(struct net *net, int af, __u32 fwmark, __u16 protocol,
                 * Check if ftp service entry exists, the packet
                 * might belong to FTP data connections.
                 */
-               svc = __ip_vs_service_find(net, af, protocol, vaddr, FTPPORT);
+               svc = __ip_vs_service_find(ipvs, af, protocol, vaddr, FTPPORT);
        }
 
        if (svc == NULL
@@ -443,7 +442,7 @@ ip_vs_service_find(struct net *net, int af, __u32 fwmark, __u16 protocol,
                /*
                 * Check if the catch-all port (port zero) exists
                 */
-               svc = __ip_vs_service_find(net, af, protocol, vaddr, 0);
+               svc = __ip_vs_service_find(ipvs, af, protocol, vaddr, 0);
        }
 
   out:
@@ -543,10 +542,9 @@ static void ip_vs_rs_unhash(struct ip_vs_dest *dest)
 }
 
 /* Check if real service by <proto,addr,port> is present */
-bool ip_vs_has_real_service(struct net *net, int af, __u16 protocol,
+bool ip_vs_has_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol,
                            const union nf_inet_addr *daddr, __be16 dport)
 {
-       struct netns_ipvs *ipvs = net_ipvs(net);
        unsigned int hash;
        struct ip_vs_dest *dest;
 
@@ -601,7 +599,7 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, int dest_af,
  * on the backup.
  * Called under RCU lock, no refcnt is returned.
  */
-struct ip_vs_dest *ip_vs_find_dest(struct net  *net, int svc_af, int dest_af,
+struct ip_vs_dest *ip_vs_find_dest(struct netns_ipvs *ipvs, int svc_af, int dest_af,
                                   const union nf_inet_addr *daddr,
                                   __be16 dport,
                                   const union nf_inet_addr *vaddr,
@@ -612,7 +610,7 @@ struct ip_vs_dest *ip_vs_find_dest(struct net  *net, int svc_af, int dest_af,
        struct ip_vs_service *svc;
        __be16 port = dport;
 
-       svc = ip_vs_service_find(net, svc_af, fwmark, protocol, vaddr, vport);
+       svc = ip_vs_service_find(ipvs, svc_af, fwmark, protocol, vaddr, vport);
        if (!svc)
                return NULL;
        if (fwmark && (flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ)
@@ -660,7 +658,7 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, int dest_af,
                     const union nf_inet_addr *daddr, __be16 dport)
 {
        struct ip_vs_dest *dest;
-       struct netns_ipvs *ipvs = net_ipvs(svc->net);
+       struct netns_ipvs *ipvs = svc->ipvs;
 
        /*
         * Find the destination in trash
@@ -715,10 +713,9 @@ static void ip_vs_dest_free(struct ip_vs_dest *dest)
  *  are expired, and the refcnt of each destination in the trash must
  *  be 0, so we simply release them here.
  */
-static void ip_vs_trash_cleanup(struct net *net)
+static void ip_vs_trash_cleanup(struct netns_ipvs *ipvs)
 {
        struct ip_vs_dest *dest, *nxt;
-       struct netns_ipvs *ipvs = net_ipvs(net);
 
        del_timer_sync(&ipvs->dest_trash_timer);
        /* No need to use dest_trash_lock */
@@ -788,7 +785,7 @@ static void
 __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
                    struct ip_vs_dest_user_kern *udest, int add)
 {
-       struct netns_ipvs *ipvs = net_ipvs(svc->net);
+       struct netns_ipvs *ipvs = svc->ipvs;
        struct ip_vs_service *old_svc;
        struct ip_vs_scheduler *sched;
        int conn_flags;
@@ -843,7 +840,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
        spin_unlock_bh(&dest->dst_lock);
 
        if (add) {
-               ip_vs_start_estimator(svc->net, &dest->stats);
+               ip_vs_start_estimator(svc->ipvs->net, &dest->stats);
                list_add_rcu(&dest->n_list, &svc->destinations);
                svc->num_dests++;
                sched = rcu_dereference_protected(svc->scheduler, 1);
@@ -874,12 +871,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
                atype = ipv6_addr_type(&udest->addr.in6);
                if ((!(atype & IPV6_ADDR_UNICAST) ||
                        atype & IPV6_ADDR_LINKLOCAL) &&
-                       !__ip_vs_addr_is_local_v6(svc->net, &udest->addr.in6))
+                       !__ip_vs_addr_is_local_v6(svc->ipvs->net, &udest->addr.in6))
                        return -EINVAL;
        } else
 #endif
        {
-               atype = inet_addr_type(svc->net, udest->addr.ip);
+               atype = inet_addr_type(svc->ipvs->net, udest->addr.ip);
                if (atype != RTN_LOCAL && atype != RTN_UNICAST)
                        return -EINVAL;
        }
@@ -1036,12 +1033,10 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
 /*
  *     Delete a destination (must be already unlinked from the service)
  */
-static void __ip_vs_del_dest(struct net *net, struct ip_vs_dest *dest,
+static void __ip_vs_del_dest(struct netns_ipvs *ipvs, struct ip_vs_dest *dest,
                             bool cleanup)
 {
-       struct netns_ipvs *ipvs = net_ipvs(net);
-
-       ip_vs_stop_estimator(net, &dest->stats);
+       ip_vs_stop_estimator(ipvs->net, &dest->stats);
 
        /*
         *  Remove it from the d-linked list with the real services.
@@ -1079,7 +1074,7 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc,
        svc->num_dests--;
 
        if (dest->af != svc->af)
-               net_ipvs(svc->net)->mixed_address_family_dests--;
+               svc->ipvs->mixed_address_family_dests--;
 
        if (svcupd) {
                struct ip_vs_scheduler *sched;
@@ -1120,7 +1115,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
        /*
         *      Delete the destination
         */
-       __ip_vs_del_dest(svc->net, dest, false);
+       __ip_vs_del_dest(svc->ipvs, dest, false);
 
        LeaveFunction(2);
 
@@ -1129,8 +1124,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
 
 static void ip_vs_dest_trash_expire(unsigned long data)
 {
-       struct net *net = (struct net *) data;
-       struct netns_ipvs *ipvs = net_ipvs(net);
+       struct netns_ipvs *ipvs = (struct netns_ipvs *)data;
        struct ip_vs_dest *dest, *next;
        unsigned long now = jiffies;
 
@@ -1163,14 +1157,13 @@ static void ip_vs_dest_trash_expire(unsigned long data)
  *     Add a service into the service hash table
  */
 static int
-ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
+ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
                  struct ip_vs_service **svc_p)
 {
        int ret = 0, i;
        struct ip_vs_scheduler *sched = NULL;
        struct ip_vs_pe *pe = NULL;
        struct ip_vs_service *svc = NULL;
-       struct netns_ipvs *ipvs = net_ipvs(net);
 
        /* increase the module use count */
        ip_vs_use_count_inc();
@@ -1237,7 +1230,7 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
        svc->flags = u->flags;
        svc->timeout = u->timeout * HZ;
        svc->netmask = u->netmask;
-       svc->net = net;
+       svc->ipvs = ipvs;
 
        INIT_LIST_HEAD(&svc->destinations);
        spin_lock_init(&svc->sched_lock);
@@ -1261,7 +1254,7 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
        else if (svc->port == 0)
                atomic_inc(&ipvs->nullsvc_counter);
 
-       ip_vs_start_estimator(net, &svc->stats);
+       ip_vs_start_estimator(ipvs->net, &svc->stats);
 
        /* Count only IPv4 services for old get/setsockopt interface */
        if (svc->af == AF_INET)
@@ -1381,7 +1374,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
        struct ip_vs_dest *dest, *nxt;
        struct ip_vs_scheduler *old_sched;
        struct ip_vs_pe *old_pe;
-       struct netns_ipvs *ipvs = net_ipvs(svc->net);
+       struct netns_ipvs *ipvs = svc->ipvs;
 
        pr_info("%s: enter\n", __func__);
 
@@ -1389,7 +1382,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
        if (svc->af == AF_INET)
                ipvs->num_services--;
 
-       ip_vs_stop_estimator(svc->net, &svc->stats);
+       ip_vs_stop_estimator(svc->ipvs->net, &svc->stats);
 
        /* Unbind scheduler */
        old_sched = rcu_dereference_protected(svc->scheduler, 1);
@@ -1405,7 +1398,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
         */
        list_for_each_entry_safe(dest, nxt, &svc->destinations, n_list) {
                __ip_vs_unlink_dest(svc, dest, 0);
-               __ip_vs_del_dest(svc->net, dest, cleanup);
+               __ip_vs_del_dest(svc->ipvs, dest, cleanup);
        }
 
        /*
@@ -1456,7 +1449,7 @@ static int ip_vs_del_service(struct ip_vs_service *svc)
 /*
  *     Flush all the virtual services
  */
-static int ip_vs_flush(struct net *net, bool cleanup)
+static int ip_vs_flush(struct netns_ipvs *ipvs, bool cleanup)
 {
        int idx;
        struct ip_vs_service *svc;
@@ -1468,7 +1461,7 @@ static int ip_vs_flush(struct net *net, bool cleanup)
        for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry_safe(svc, n, &ip_vs_svc_table[idx],
                                          s_list) {
-                       if (net_eq(svc->net, net))
+                       if (svc->ipvs == ipvs)
                                ip_vs_unlink_service(svc, cleanup);
                }
        }
@@ -1479,7 +1472,7 @@ static int ip_vs_flush(struct net *net, bool cleanup)
        for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry_safe(svc, n, &ip_vs_svc_fwm_table[idx],
                                          f_list) {
-                       if (net_eq(svc->net, net))
+                       if (svc->ipvs == ipvs)
                                ip_vs_unlink_service(svc, cleanup);
                }
        }
@@ -1491,12 +1484,12 @@ static int ip_vs_flush(struct net *net, bool cleanup)
  *     Delete service by {netns} in the service table.
  *     Called by __ip_vs_cleanup()
  */
-void ip_vs_service_net_cleanup(struct net *net)
+void ip_vs_service_net_cleanup(struct netns_ipvs *ipvs)
 {
        EnterFunction(2);
        /* Check for "full" addressed entries */
        mutex_lock(&__ip_vs_mutex);
-       ip_vs_flush(net, true);
+       ip_vs_flush(ipvs, true);
        mutex_unlock(&__ip_vs_mutex);
        LeaveFunction(2);
 }
@@ -1540,7 +1533,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
        mutex_lock(&__ip_vs_mutex);
        for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
-                       if (net_eq(svc->net, net)) {
+                       if (svc->ipvs == ipvs) {
                                list_for_each_entry(dest, &svc->destinations,
                                                    n_list) {
                                        ip_vs_forget_dev(dest, dev);
@@ -1549,7 +1542,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
                }
 
                hlist_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
-                       if (net_eq(svc->net, net)) {
+                       if (svc->ipvs == ipvs) {
                                list_for_each_entry(dest, &svc->destinations,
                                                    n_list) {
                                        ip_vs_forget_dev(dest, dev);
@@ -1583,26 +1576,26 @@ static int ip_vs_zero_service(struct ip_vs_service *svc)
        return 0;
 }
 
-static int ip_vs_zero_all(struct net *net)
+static int ip_vs_zero_all(struct netns_ipvs *ipvs)
 {
        int idx;
        struct ip_vs_service *svc;
 
        for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
-                       if (net_eq(svc->net, net))
+                       if (svc->ipvs == ipvs)
                                ip_vs_zero_service(svc);
                }
        }
 
        for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
-                       if (net_eq(svc->net, net))
+                       if (svc->ipvs == ipvs)
                                ip_vs_zero_service(svc);
                }
        }
 
-       ip_vs_zero_stats(&net_ipvs(net)->tot_stats);
+       ip_vs_zero_stats(&ipvs->tot_stats);
        return 0;
 }
 
@@ -1615,7 +1608,7 @@ static int
 proc_do_defense_mode(struct ctl_table *table, int write,
                     void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       struct net *net = current->nsproxy->net_ns;
+       struct netns_ipvs *ipvs = table->extra2;
        int *valp = table->data;
        int val = *valp;
        int rc;
@@ -1626,7 +1619,7 @@ proc_do_defense_mode(struct ctl_table *table, int write,
                        /* Restore the correct value */
                        *valp = val;
                } else {
-                       update_defense_level(net_ipvs(net));
+                       update_defense_level(ipvs);
                }
        }
        return rc;
@@ -1844,6 +1837,18 @@ static struct ctl_table vs_vars[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+       {
+               .procname       = "schedule_icmp",
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       {
+               .procname       = "ignore_tunneled",
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
 #ifdef CONFIG_IP_VS_DEBUG
        {
                .procname       = "debug_level",
@@ -1889,6 +1894,7 @@ static inline const char *ip_vs_fwd_name(unsigned int flags)
 static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
 {
        struct net *net = seq_file_net(seq);
+       struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_iter *iter = seq->private;
        int idx;
        struct ip_vs_service *svc;
@@ -1896,7 +1902,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
        /* look in hash by protocol */
        for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry_rcu(svc, &ip_vs_svc_table[idx], s_list) {
-                       if (net_eq(svc->net, net) && pos-- == 0) {
+                       if ((svc->ipvs == ipvs) && pos-- == 0) {
                                iter->table = ip_vs_svc_table;
                                iter->bucket = idx;
                                return svc;
@@ -1908,7 +1914,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
        for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry_rcu(svc, &ip_vs_svc_fwm_table[idx],
                                         f_list) {
-                       if (net_eq(svc->net, net) && pos-- == 0) {
+                       if ((svc->ipvs == ipvs) && pos-- == 0) {
                                iter->table = ip_vs_svc_fwm_table;
                                iter->bucket = idx;
                                return svc;
@@ -2196,7 +2202,7 @@ static const struct file_operations ip_vs_stats_percpu_fops = {
 /*
  *     Set timeout values for tcp tcpfin udp in the timeout_table.
  */
-static int ip_vs_set_timeout(struct net *net, struct ip_vs_timeout_user *u)
+static int ip_vs_set_timeout(struct netns_ipvs *ipvs, struct ip_vs_timeout_user *u)
 {
 #if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
        struct ip_vs_proto_data *pd;
@@ -2209,13 +2215,13 @@ static int ip_vs_set_timeout(struct net *net, struct ip_vs_timeout_user *u)
 
 #ifdef CONFIG_IP_VS_PROTO_TCP
        if (u->tcp_timeout) {
-               pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+               pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP);
                pd->timeout_table[IP_VS_TCP_S_ESTABLISHED]
                        = u->tcp_timeout * HZ;
        }
 
        if (u->tcp_fin_timeout) {
-               pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+               pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP);
                pd->timeout_table[IP_VS_TCP_S_FIN_WAIT]
                        = u->tcp_fin_timeout * HZ;
        }
@@ -2223,7 +2229,7 @@ static int ip_vs_set_timeout(struct net *net, struct ip_vs_timeout_user *u)
 
 #ifdef CONFIG_IP_VS_PROTO_UDP
        if (u->udp_timeout) {
-               pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
+               pd = ip_vs_proto_data_get(ipvs, IPPROTO_UDP);
                pd->timeout_table[IP_VS_UDP_S_NORMAL]
                        = u->udp_timeout * HZ;
        }
@@ -2335,24 +2341,34 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
            cmd == IP_VS_SO_SET_STOPDAEMON) {
                struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
 
-               mutex_lock(&ipvs->sync_mutex);
-               if (cmd == IP_VS_SO_SET_STARTDAEMON)
-                       ret = start_sync_thread(net, dm->state, dm->mcast_ifn,
-                                               dm->syncid);
-               else
+               if (cmd == IP_VS_SO_SET_STARTDAEMON) {
+                       struct ipvs_sync_daemon_cfg cfg;
+
+                       memset(&cfg, 0, sizeof(cfg));
+                       strlcpy(cfg.mcast_ifn, dm->mcast_ifn,
+                               sizeof(cfg.mcast_ifn));
+                       cfg.syncid = dm->syncid;
+                       rtnl_lock();
+                       mutex_lock(&ipvs->sync_mutex);
+                       ret = start_sync_thread(net, &cfg, dm->state);
+                       mutex_unlock(&ipvs->sync_mutex);
+                       rtnl_unlock();
+               } else {
+                       mutex_lock(&ipvs->sync_mutex);
                        ret = stop_sync_thread(net, dm->state);
-               mutex_unlock(&ipvs->sync_mutex);
+                       mutex_unlock(&ipvs->sync_mutex);
+               }
                goto out_dec;
        }
 
        mutex_lock(&__ip_vs_mutex);
        if (cmd == IP_VS_SO_SET_FLUSH) {
                /* Flush the virtual service */
-               ret = ip_vs_flush(net, false);
+               ret = ip_vs_flush(ipvs, false);
                goto out_unlock;
        } else if (cmd == IP_VS_SO_SET_TIMEOUT) {
                /* Set timeout values for (tcp tcpfin udp) */
-               ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg);
+               ret = ip_vs_set_timeout(ipvs, (struct ip_vs_timeout_user *)arg);
                goto out_unlock;
        }
 
@@ -2367,7 +2383,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
        if (cmd == IP_VS_SO_SET_ZERO) {
                /* if no service address is set, zero counters in all */
                if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) {
-                       ret = ip_vs_zero_all(net);
+                       ret = ip_vs_zero_all(ipvs);
                        goto out_unlock;
                }
        }
@@ -2385,10 +2401,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
        /* Lookup the exact service by <protocol, addr, port> or fwmark */
        rcu_read_lock();
        if (usvc.fwmark == 0)
-               svc = __ip_vs_service_find(net, usvc.af, usvc.protocol,
+               svc = __ip_vs_service_find(ipvs, usvc.af, usvc.protocol,
                                           &usvc.addr, usvc.port);
        else
-               svc = __ip_vs_svc_fwm_find(net, usvc.af, usvc.fwmark);
+               svc = __ip_vs_svc_fwm_find(ipvs, usvc.af, usvc.fwmark);
        rcu_read_unlock();
 
        if (cmd != IP_VS_SO_SET_ADD
@@ -2402,7 +2418,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
                if (svc != NULL)
                        ret = -EEXIST;
                else
-                       ret = ip_vs_add_service(net, &usvc, &svc);
+                       ret = ip_vs_add_service(ipvs, &usvc, &svc);
                break;
        case IP_VS_SO_SET_EDIT:
                ret = ip_vs_edit_service(svc, &usvc);
@@ -2461,7 +2477,7 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
 }
 
 static inline int
-__ip_vs_get_service_entries(struct net *net,
+__ip_vs_get_service_entries(struct netns_ipvs *ipvs,
                            const struct ip_vs_get_services *get,
                            struct ip_vs_get_services __user *uptr)
 {
@@ -2473,7 +2489,7 @@ __ip_vs_get_service_entries(struct net *net,
        for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
                        /* Only expose IPv4 entries to old interface */
-                       if (svc->af != AF_INET || !net_eq(svc->net, net))
+                       if (svc->af != AF_INET || (svc->ipvs != ipvs))
                                continue;
 
                        if (count >= get->num_services)
@@ -2492,7 +2508,7 @@ __ip_vs_get_service_entries(struct net *net,
        for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
                hlist_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
                        /* Only expose IPv4 entries to old interface */
-                       if (svc->af != AF_INET || !net_eq(svc->net, net))
+                       if (svc->af != AF_INET || (svc->ipvs != ipvs))
                                continue;
 
                        if (count >= get->num_services)
@@ -2515,15 +2531,16 @@ static inline int
 __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
                         struct ip_vs_get_dests __user *uptr)
 {
+       struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_service *svc;
        union nf_inet_addr addr = { .ip = get->addr };
        int ret = 0;
 
        rcu_read_lock();
        if (get->fwmark)
-               svc = __ip_vs_svc_fwm_find(net, AF_INET, get->fwmark);
+               svc = __ip_vs_svc_fwm_find(ipvs, AF_INET, get->fwmark);
        else
-               svc = __ip_vs_service_find(net, AF_INET, get->protocol, &addr,
+               svc = __ip_vs_service_find(ipvs, AF_INET, get->protocol, &addr,
                                           get->port);
        rcu_read_unlock();
 
@@ -2571,18 +2588,19 @@ static inline void
 __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
 {
 #if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
+       struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_proto_data *pd;
 #endif
 
        memset(u, 0, sizeof (*u));
 
 #ifdef CONFIG_IP_VS_PROTO_TCP
-       pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+       pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP);
        u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
        u->tcp_fin_timeout = pd->timeout_table[IP_VS_TCP_S_FIN_WAIT] / HZ;
 #endif
 #ifdef CONFIG_IP_VS_PROTO_UDP
-       pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
+       pd = ip_vs_proto_data_get(ipvs, IPPROTO_UDP);
        u->udp_timeout =
                        pd->timeout_table[IP_VS_UDP_S_NORMAL] / HZ;
 #endif
@@ -2645,15 +2663,15 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
                mutex_lock(&ipvs->sync_mutex);
                if (ipvs->sync_state & IP_VS_STATE_MASTER) {
                        d[0].state = IP_VS_STATE_MASTER;
-                       strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn,
+                       strlcpy(d[0].mcast_ifn, ipvs->mcfg.mcast_ifn,
                                sizeof(d[0].mcast_ifn));
-                       d[0].syncid = ipvs->master_syncid;
+                       d[0].syncid = ipvs->mcfg.syncid;
                }
                if (ipvs->sync_state & IP_VS_STATE_BACKUP) {
                        d[1].state = IP_VS_STATE_BACKUP;
-                       strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn,
+                       strlcpy(d[1].mcast_ifn, ipvs->bcfg.mcast_ifn,
                                sizeof(d[1].mcast_ifn));
-                       d[1].syncid = ipvs->backup_syncid;
+                       d[1].syncid = ipvs->bcfg.syncid;
                }
                if (copy_to_user(user, &d, sizeof(d)) != 0)
                        ret = -EFAULT;
@@ -2701,7 +2719,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
                        ret = -EINVAL;
                        goto out;
                }
-               ret = __ip_vs_get_service_entries(net, get, user);
+               ret = __ip_vs_get_service_entries(ipvs, get, user);
        }
        break;
 
@@ -2715,9 +2733,9 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
                addr.ip = entry->addr;
                rcu_read_lock();
                if (entry->fwmark)
-                       svc = __ip_vs_svc_fwm_find(net, AF_INET, entry->fwmark);
+                       svc = __ip_vs_svc_fwm_find(ipvs, AF_INET, entry->fwmark);
                else
-                       svc = __ip_vs_service_find(net, AF_INET,
+                       svc = __ip_vs_service_find(ipvs, AF_INET,
                                                   entry->protocol, &addr,
                                                   entry->port);
                rcu_read_unlock();
@@ -2808,6 +2826,11 @@ static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = {
        [IPVS_DAEMON_ATTR_MCAST_IFN]    = { .type = NLA_NUL_STRING,
                                            .len = IP_VS_IFNAME_MAXLEN },
        [IPVS_DAEMON_ATTR_SYNC_ID]      = { .type = NLA_U32 },
+       [IPVS_DAEMON_ATTR_SYNC_MAXLEN]  = { .type = NLA_U16 },
+       [IPVS_DAEMON_ATTR_MCAST_GROUP]  = { .type = NLA_U32 },
+       [IPVS_DAEMON_ATTR_MCAST_GROUP6] = { .len = sizeof(struct in6_addr) },
+       [IPVS_DAEMON_ATTR_MCAST_PORT]   = { .type = NLA_U16 },
+       [IPVS_DAEMON_ATTR_MCAST_TTL]    = { .type = NLA_U8 },
 };
 
 /* Policy used for attributes in nested attribute IPVS_CMD_ATTR_SERVICE */
@@ -2981,12 +3004,12 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb,
        int idx = 0, i;
        int start = cb->args[0];
        struct ip_vs_service *svc;
-       struct net *net = skb_sknet(skb);
+       struct netns_ipvs *ipvs = net_ipvs(skb_sknet(skb));
 
        mutex_lock(&__ip_vs_mutex);
        for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) {
                hlist_for_each_entry(svc, &ip_vs_svc_table[i], s_list) {
-                       if (++idx <= start || !net_eq(svc->net, net))
+                       if (++idx <= start || (svc->ipvs != ipvs))
                                continue;
                        if (ip_vs_genl_dump_service(skb, svc, cb) < 0) {
                                idx--;
@@ -2997,7 +3020,7 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb,
 
        for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) {
                hlist_for_each_entry(svc, &ip_vs_svc_fwm_table[i], f_list) {
-                       if (++idx <= start || !net_eq(svc->net, net))
+                       if (++idx <= start || (svc->ipvs != ipvs))
                                continue;
                        if (ip_vs_genl_dump_service(skb, svc, cb) < 0) {
                                idx--;
@@ -3018,6 +3041,7 @@ static int ip_vs_genl_parse_service(struct net *net,
                                    struct nlattr *nla, int full_entry,
                                    struct ip_vs_service **ret_svc)
 {
+       struct netns_ipvs *ipvs = net_ipvs(net);
        struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1];
        struct nlattr *nla_af, *nla_port, *nla_fwmark, *nla_protocol, *nla_addr;
        struct ip_vs_service *svc;
@@ -3058,9 +3082,9 @@ static int ip_vs_genl_parse_service(struct net *net,
 
        rcu_read_lock();
        if (usvc->fwmark)
-               svc = __ip_vs_svc_fwm_find(net, usvc->af, usvc->fwmark);
+               svc = __ip_vs_svc_fwm_find(ipvs, usvc->af, usvc->fwmark);
        else
-               svc = __ip_vs_service_find(net, usvc->af, usvc->protocol,
+               svc = __ip_vs_service_find(ipvs, usvc->af, usvc->protocol,
                                           &usvc->addr, usvc->port);
        rcu_read_unlock();
        *ret_svc = svc;
@@ -3266,7 +3290,7 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
 }
 
 static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state,
-                                 const char *mcast_ifn, __u32 syncid)
+                                 struct ipvs_sync_daemon_cfg *c)
 {
        struct nlattr *nl_daemon;
 
@@ -3275,9 +3299,23 @@ static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state,
                return -EMSGSIZE;
 
        if (nla_put_u32(skb, IPVS_DAEMON_ATTR_STATE, state) ||
-           nla_put_string(skb, IPVS_DAEMON_ATTR_MCAST_IFN, mcast_ifn) ||
-           nla_put_u32(skb, IPVS_DAEMON_ATTR_SYNC_ID, syncid))
+           nla_put_string(skb, IPVS_DAEMON_ATTR_MCAST_IFN, c->mcast_ifn) ||
+           nla_put_u32(skb, IPVS_DAEMON_ATTR_SYNC_ID, c->syncid) ||
+           nla_put_u16(skb, IPVS_DAEMON_ATTR_SYNC_MAXLEN, c->sync_maxlen) ||
+           nla_put_u16(skb, IPVS_DAEMON_ATTR_MCAST_PORT, c->mcast_port) ||
+           nla_put_u8(skb, IPVS_DAEMON_ATTR_MCAST_TTL, c->mcast_ttl))
                goto nla_put_failure;
+#ifdef CONFIG_IP_VS_IPV6
+       if (c->mcast_af == AF_INET6) {
+               if (nla_put_in6_addr(skb, IPVS_DAEMON_ATTR_MCAST_GROUP6,
+                                    &c->mcast_group.in6))
+                       goto nla_put_failure;
+       } else
+#endif
+               if (c->mcast_af == AF_INET &&
+                   nla_put_in_addr(skb, IPVS_DAEMON_ATTR_MCAST_GROUP,
+                                   c->mcast_group.ip))
+                       goto nla_put_failure;
        nla_nest_end(skb, nl_daemon);
 
        return 0;
@@ -3288,7 +3326,7 @@ nla_put_failure:
 }
 
 static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __u32 state,
-                                 const char *mcast_ifn, __u32 syncid,
+                                 struct ipvs_sync_daemon_cfg *c,
                                  struct netlink_callback *cb)
 {
        void *hdr;
@@ -3298,7 +3336,7 @@ static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __u32 state,
        if (!hdr)
                return -EMSGSIZE;
 
-       if (ip_vs_genl_fill_daemon(skb, state, mcast_ifn, syncid))
+       if (ip_vs_genl_fill_daemon(skb, state, c))
                goto nla_put_failure;
 
        genlmsg_end(skb, hdr);
@@ -3318,8 +3356,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb,
        mutex_lock(&ipvs->sync_mutex);
        if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) {
                if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER,
-                                          ipvs->master_mcast_ifn,
-                                          ipvs->master_syncid, cb) < 0)
+                                          &ipvs->mcfg, cb) < 0)
                        goto nla_put_failure;
 
                cb->args[0] = 1;
@@ -3327,8 +3364,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb,
 
        if ((ipvs->sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) {
                if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP,
-                                          ipvs->backup_mcast_ifn,
-                                          ipvs->backup_syncid, cb) < 0)
+                                          &ipvs->bcfg, cb) < 0)
                        goto nla_put_failure;
 
                cb->args[1] = 1;
@@ -3342,34 +3378,88 @@ nla_put_failure:
 
 static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs)
 {
+       struct netns_ipvs *ipvs = net_ipvs(net);
+       struct ipvs_sync_daemon_cfg c;
+       struct nlattr *a;
+       int ret;
+
+       memset(&c, 0, sizeof(c));
        if (!(attrs[IPVS_DAEMON_ATTR_STATE] &&
              attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&
              attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
                return -EINVAL;
+       strlcpy(c.mcast_ifn, nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
+               sizeof(c.mcast_ifn));
+       c.syncid = nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID]);
+
+       a = attrs[IPVS_DAEMON_ATTR_SYNC_MAXLEN];
+       if (a)
+               c.sync_maxlen = nla_get_u16(a);
+
+       a = attrs[IPVS_DAEMON_ATTR_MCAST_GROUP];
+       if (a) {
+               c.mcast_af = AF_INET;
+               c.mcast_group.ip = nla_get_in_addr(a);
+               if (!ipv4_is_multicast(c.mcast_group.ip))
+                       return -EINVAL;
+       } else {
+               a = attrs[IPVS_DAEMON_ATTR_MCAST_GROUP6];
+               if (a) {
+#ifdef CONFIG_IP_VS_IPV6
+                       int addr_type;
+
+                       c.mcast_af = AF_INET6;
+                       c.mcast_group.in6 = nla_get_in6_addr(a);
+                       addr_type = ipv6_addr_type(&c.mcast_group.in6);
+                       if (!(addr_type & IPV6_ADDR_MULTICAST))
+                               return -EINVAL;
+#else
+                       return -EAFNOSUPPORT;
+#endif
+               }
+       }
+
+       a = attrs[IPVS_DAEMON_ATTR_MCAST_PORT];
+       if (a)
+               c.mcast_port = nla_get_u16(a);
+
+       a = attrs[IPVS_DAEMON_ATTR_MCAST_TTL];
+       if (a)
+               c.mcast_ttl = nla_get_u8(a);
 
        /* The synchronization protocol is incompatible with mixed family
         * services
         */
-       if (net_ipvs(net)->mixed_address_family_dests > 0)
+       if (ipvs->mixed_address_family_dests > 0)
                return -EINVAL;
 
-       return start_sync_thread(net,
-                                nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]),
-                                nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
-                                nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID]));
+       rtnl_lock();
+       mutex_lock(&ipvs->sync_mutex);
+       ret = start_sync_thread(net, &c,
+                               nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
+       mutex_unlock(&ipvs->sync_mutex);
+       rtnl_unlock();
+       return ret;
 }
 
 static int ip_vs_genl_del_daemon(struct net *net, struct nlattr **attrs)
 {
+       struct netns_ipvs *ipvs = net_ipvs(net);
+       int ret;
+
        if (!attrs[IPVS_DAEMON_ATTR_STATE])
                return -EINVAL;
 
-       return stop_sync_thread(net,
-                               nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
+       mutex_lock(&ipvs->sync_mutex);
+       ret = stop_sync_thread(net,
+                              nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
+       mutex_unlock(&ipvs->sync_mutex);
+       return ret;
 }
 
 static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs)
 {
+       struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_timeout_user t;
 
        __ip_vs_get_timeouts(net, &t);
@@ -3384,12 +3474,12 @@ static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs)
        if (attrs[IPVS_CMD_ATTR_TIMEOUT_UDP])
                t.udp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]);
 
-       return ip_vs_set_timeout(net, &t);
+       return ip_vs_set_timeout(ipvs, &t);
 }
 
 static int ip_vs_genl_set_daemon(struct sk_buff *skb, struct genl_info *info)
 {
-       int ret = 0, cmd;
+       int ret = -EINVAL, cmd;
        struct net *net;
        struct netns_ipvs *ipvs;
 
@@ -3400,22 +3490,19 @@ static int ip_vs_genl_set_daemon(struct sk_buff *skb, struct genl_info *info)
        if (cmd == IPVS_CMD_NEW_DAEMON || cmd == IPVS_CMD_DEL_DAEMON) {
                struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1];
 
-               mutex_lock(&ipvs->sync_mutex);
                if (!info->attrs[IPVS_CMD_ATTR_DAEMON] ||
                    nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX,
                                     info->attrs[IPVS_CMD_ATTR_DAEMON],
-                                    ip_vs_daemon_policy)) {
-                       ret = -EINVAL;
+                                    ip_vs_daemon_policy))
                        goto out;
-               }
 
                if (cmd == IPVS_CMD_NEW_DAEMON)
                        ret = ip_vs_genl_new_daemon(net, daemon_attrs);
                else
                        ret = ip_vs_genl_del_daemon(net, daemon_attrs);
-out:
-               mutex_unlock(&ipvs->sync_mutex);
        }
+
+out:
        return ret;
 }
 
@@ -3427,21 +3514,23 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
        int ret = 0, cmd;
        int need_full_svc = 0, need_full_dest = 0;
        struct net *net;
+       struct netns_ipvs *ipvs;
 
        net = skb_sknet(skb);
+       ipvs = net_ipvs(net);
        cmd = info->genlhdr->cmd;
 
        mutex_lock(&__ip_vs_mutex);
 
        if (cmd == IPVS_CMD_FLUSH) {
-               ret = ip_vs_flush(net, false);
+               ret = ip_vs_flush(ipvs, false);
                goto out;
        } else if (cmd == IPVS_CMD_SET_CONFIG) {
                ret = ip_vs_genl_set_config(net, info->attrs);
                goto out;
        } else if (cmd == IPVS_CMD_ZERO &&
                   !info->attrs[IPVS_CMD_ATTR_SERVICE]) {
-               ret = ip_vs_zero_all(net);
+               ret = ip_vs_zero_all(ipvs);
                goto out;
        }
 
@@ -3490,7 +3579,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
                        /* The synchronization protocol is incompatible
                         * with mixed family services
                         */
-                       if (net_ipvs(net)->sync_state) {
+                       if (ipvs->sync_state) {
                                ret = -EINVAL;
                                goto out;
                        }
@@ -3510,7 +3599,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
        switch (cmd) {
        case IPVS_CMD_NEW_SERVICE:
                if (svc == NULL)
-                       ret = ip_vs_add_service(net, &usvc, &svc);
+                       ret = ip_vs_add_service(ipvs, &usvc, &svc);
                else
                        ret = -EEXIST;
                break;
@@ -3777,6 +3866,10 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
        } else
                tbl = vs_vars;
        /* Initialize sysctl defaults */
+       for (idx = 0; idx < ARRAY_SIZE(vs_vars); idx++) {
+               if (tbl[idx].proc_handler == proc_do_defense_mode)
+                       tbl[idx].extra2 = ipvs;
+       }
        idx = 0;
        ipvs->sysctl_amemthresh = 1024;
        tbl[idx++].data = &ipvs->sysctl_amemthresh;
@@ -3818,7 +3911,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
        tbl[idx++].data = &ipvs->sysctl_backup_only;
        ipvs->sysctl_conn_reuse_mode = 1;
        tbl[idx++].data = &ipvs->sysctl_conn_reuse_mode;
-
+       tbl[idx++].data = &ipvs->sysctl_schedule_icmp;
+       tbl[idx++].data = &ipvs->sysctl_ignore_tunneled;
 
        ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl);
        if (ipvs->sysctl_hdr == NULL) {
@@ -3871,7 +3965,7 @@ int __net_init ip_vs_control_net_init(struct net *net)
        INIT_LIST_HEAD(&ipvs->dest_trash);
        spin_lock_init(&ipvs->dest_trash_lock);
        setup_timer(&ipvs->dest_trash_timer, ip_vs_dest_trash_expire,
-                   (unsigned long) net);
+                   (unsigned long) ipvs);
        atomic_set(&ipvs->ftpsvc_counter, 0);
        atomic_set(&ipvs->nullsvc_counter, 0);
 
@@ -3907,7 +4001,7 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
-       ip_vs_trash_cleanup(net);
+       ip_vs_trash_cleanup(ipvs);
        ip_vs_control_net_cleanup_sysctl(net);
        remove_proc_entry("ip_vs_stats_percpu", net->proc_net);
        remove_proc_entry("ip_vs_stats", net->proc_net);
This page took 0.040054 seconds and 5 git commands to generate.