[CRIU] [PATCH] net: virtualize sock diag

Pavel Emelyanov xemul at parallels.com
Sun Jul 15 23:02:53 EDT 2012


On 07/15/2012 04:27 AM, Andrew Vagin wrote:
> We need something like this
> 
> Signed-off-by: Andrew Vagin <avagin at openvz.org>

Acked-by: Pavel Emelyanov <xemul at parallels.com>

Cyrill, plz, merge this in kernel repo (when rebasing to new -rc)
Andrey, plz, prepare and send this patch to netdev@, cc David Miller and me.

> ---
>  include/linux/sock_diag.h   |    1 -
>  include/net/net_namespace.h |    1 +
>  net/core/sock_diag.c        |   28 ++++++++++++++++++++++++----
>  net/ipv4/inet_diag.c        |    9 ++++++---
>  net/ipv4/udp_diag.c         |    3 ++-
>  net/unix/diag.c             |    6 ++++--
>  6 files changed, 37 insertions(+), 11 deletions(-)
> 
> diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
> index db4bae7..ac30fb5 100644
> --- a/include/linux/sock_diag.h
> +++ b/include/linux/sock_diag.h
> @@ -43,6 +43,5 @@ void sock_diag_save_cookie(void *sk, __u32 *cookie);
>  
>  int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr);
>  
> -extern struct sock *sock_diag_nlsk;
>  #endif /* KERNEL */
>  #endif
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index ac9195e..3060918 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -101,6 +101,7 @@ struct net {
>  	struct netns_xfrm	xfrm;
>  #endif
>  	struct netns_ipvs	*ipvs;
> +	struct sock		*sock_diag_nlsk;
>  };
>  
>  
> diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
> index 5fd1467..b04833f 100644
> --- a/net/core/sock_diag.c
> +++ b/net/core/sock_diag.c
> @@ -174,16 +174,36 @@ static void sock_diag_rcv(struct sk_buff *skb)
>  struct sock *sock_diag_nlsk;
>  EXPORT_SYMBOL_GPL(sock_diag_nlsk);
>  
> -static int __init sock_diag_init(void)
> +static int __net_init diag_net_init(struct net *net)
>  {
> -	sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, 0,
> +	net->sock_diag_nlsk = netlink_kernel_create(net, NETLINK_INET_DIAG, 0,
>  					sock_diag_rcv, NULL, THIS_MODULE);
> -	return sock_diag_nlsk == NULL ? -ENOMEM : 0;
> +	if (net->sock_diag_nlsk == NULL)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +static void __net_exit diag_net_exit(struct net *net)
> +{
> +	netlink_kernel_release(net->sock_diag_nlsk);
> +	net->sock_diag_nlsk = NULL;
> +}
> +
> +static struct pernet_operations diag_net_ops = {
> +	.init = diag_net_init,
> +	.exit = diag_net_exit,
> +};
> +
> +static int __init sock_diag_init(void)
> +{
> +	register_pernet_subsys(&diag_net_ops);
> +	return 0;
>  }
>  
>  static void __exit sock_diag_exit(void)
>  {
> -	netlink_kernel_release(sock_diag_nlsk);
> +	unregister_pernet_subsys(&diag_net_ops);
>  }
>  
>  module_init(sock_diag_init);
> diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
> index 46d1e71..444e787 100644
> --- a/net/ipv4/inet_diag.c
> +++ b/net/ipv4/inet_diag.c
> @@ -269,6 +269,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
>  	int err;
>  	struct sock *sk;
>  	struct sk_buff *rep;
> +	struct net *net = sock_net(in_skb->sk);
>  
>  	err = -EINVAL;
>  	if (req->sdiag_family == AF_INET) {
> @@ -314,7 +315,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
>  		kfree_skb(rep);
>  		goto out;
>  	}
> -	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
> +	err = netlink_unicast(net->sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
>  			      MSG_DONTWAIT);
>  	if (err > 0)
>  		err = 0;
> @@ -944,6 +945,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
>  static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
>  {
>  	int hdrlen = sizeof(struct inet_diag_req);
> +	struct net *net = sock_net(skb->sk);
>  
>  	if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX ||
>  	    nlmsg_len(nlh) < hdrlen)
> @@ -964,7 +966,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
>  			struct netlink_dump_control c = {
>  				.dump = inet_diag_dump_compat,
>  			};
> -			return netlink_dump_start(sock_diag_nlsk, skb, nlh, &c);
> +			return netlink_dump_start(net->sock_diag_nlsk, skb, nlh, &c);
>  		}
>  	}
>  
> @@ -974,6 +976,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
>  static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
>  {
>  	int hdrlen = sizeof(struct inet_diag_req_v2);
> +	struct net *net = sock_net(skb->sk);
>  
>  	if (nlmsg_len(h) < hdrlen)
>  		return -EINVAL;
> @@ -992,7 +995,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
>  			struct netlink_dump_control c = {
>  				.dump = inet_diag_dump,
>  			};
> -			return netlink_dump_start(sock_diag_nlsk, skb, h, &c);
> +			return netlink_dump_start(net->sock_diag_nlsk, skb, h, &c);
>  		}
>  	}
>  
> diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
> index a7f86a3..d2198c1 100644
> --- a/net/ipv4/udp_diag.c
> +++ b/net/ipv4/udp_diag.c
> @@ -34,6 +34,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
>  	int err = -EINVAL;
>  	struct sock *sk;
>  	struct sk_buff *rep;
> +	struct net *net = sock_net(in_skb->sk);
>  
>  	if (req->sdiag_family == AF_INET)
>  		sk = __udp4_lib_lookup(&init_net,
> @@ -75,7 +76,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
>  		kfree_skb(rep);
>  		goto out;
>  	}
> -	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
> +	err = netlink_unicast(net->sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
>  			      MSG_DONTWAIT);
>  	if (err > 0)
>  		err = 0;
> diff --git a/net/unix/diag.c b/net/unix/diag.c
> index 47d3002..f621746 100644
> --- a/net/unix/diag.c
> +++ b/net/unix/diag.c
> @@ -252,6 +252,7 @@ static int unix_diag_get_exact(struct sk_buff *in_skb,
>  	struct sock *sk;
>  	struct sk_buff *rep;
>  	unsigned int extra_len;
> +	struct net *net = sock_net(in_skb->sk);
>  
>  	if (req->udiag_ino == 0)
>  		goto out_nosk;
> @@ -283,7 +284,7 @@ again:
>  
>  		goto again;
>  	}
> -	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
> +	err = netlink_unicast(net->sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
>  			      MSG_DONTWAIT);
>  	if (err > 0)
>  		err = 0;
> @@ -297,6 +298,7 @@ out_nosk:
>  static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
>  {
>  	int hdrlen = sizeof(struct unix_diag_req);
> +	struct net *net = sock_net(skb->sk);
>  
>  	if (nlmsg_len(h) < hdrlen)
>  		return -EINVAL;
> @@ -305,7 +307,7 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
>  		struct netlink_dump_control c = {
>  			.dump = unix_diag_dump,
>  		};
> -		return netlink_dump_start(sock_diag_nlsk, skb, h, &c);
> +		return netlink_dump_start(net->sock_diag_nlsk, skb, h, &c);
>  	} else
>  		return unix_diag_get_exact(skb, h, (struct unix_diag_req *)NLMSG_DATA(h));
>  }



More information about the CRIU mailing list