[CRIU] Re: [PATCH 6/7] sockets: Restore unbound inet sockets

Pavel Emelyanov xemul at parallels.com
Tue May 15 16:56:24 EDT 2012


On 05/12/2012 07:47 PM, Cyrill Gorcunov wrote:
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  sk-inet.c |  176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
>  sockets.c |   10 +++-
>  2 files changed, 174 insertions(+), 12 deletions(-)
> 

> +static struct inet_sk_desc *gen_uncon_sk(int lfd, const struct fd_parms *p)
> +{
> +	struct inet_sk_desc *sk = xzalloc(sizeof(*sk));
> +	union {
> +		struct sockaddr_in	v4;
> +		struct sockaddr_in6	v6;
> +	} addr;
> +	socklen_t len;
> +	int ret = 0;
> +
> +	if (!sk)
> +		goto err;
> +
> +#define __CR_GET_SOPT(lfd, n, v)					\
> +	({								\
> +		len = sizeof(*v);					\
> +		int __r = getsockopt(lfd, SOL_SOCKET, n, v, &len);	\
> +		if (__r)						\
> +			pr_perror("getsockopt failed on %d", p->fd);	\
> +		__r;							\
> +	})

Use do_dump_opt from sockets.c file. They do this error reporting and
also check option length to be correct.

> +	sk->sd.ino	= p->stat.st_ino;
> +	sk->state	= TCP_CLOSE;
> +
> +	/*
> +	 * The restored application will pass backlog explicitly
> +	 * on a listen call (if needed) so put some sane value here.
> +	 */
> +	sk->wqlen	= 16;
> +
> +	ret |= __CR_GET_SOPT(lfd, SO_DOMAIN, &sk->sd.family);
> +	ret |= __CR_GET_SOPT(lfd, SO_TYPE, &sk->type);
> +	ret |= __CR_GET_SOPT(lfd, SO_PROTOCOL, &sk->proto);
> +	if (ret)
> +		goto err;
> +
> +#undef __CR_GET_SOPT
> +
> +
> +	switch (sk->sd.family) {
> +	case AF_INET:
> +	case AF_INET6:
> +		break;
> +	default:
> +		pr_err("Unsupported socket family %d on %d\n",
> +		       sk->sd.family, p->fd);
> +		goto err;
> +	}
> +
> +	switch (sk->type) {
> +	case SOCK_DGRAM:
> +	case SOCK_STREAM:
> +		break;
> +	default:
> +		pr_err("Unsupported socket type %d on %d\n",
> +		       sk->type, p->fd);
> +		goto err;
> +	}

This check is done in generic inet socket dump

> +	switch (sk->proto) {
> +	case IPPROTO_IP:
> +	case IPPROTO_TCP:
> +	case IPPROTO_UDP:
> +	case IPPROTO_UDPLITE:
> +		break;
> +	default:
> +		pr_err("Unsupported socket proto %d on %d\n",
> +		       sk->proto, p->fd);
> +		goto err;
> +	}

So is this.

> +	if (sk->sd.family == AF_INET) {
> +		len = sizeof(addr.v4);
> +		ret = getsockname(lfd, (struct sockaddr *)&addr.v4, &len);

This requires an explanation. If a socket has a name, this means it's bound,
but in this case it should have been reported via netlink.

> +		if (ret) {
> +			if (errno != ENOTCONN) {
> +				pr_perror("getsockname failed on %d", p->fd);
> +				goto err;
> +			}
> +		} else {
> +			sk->src_port = addr.v4.sin_port;
> +			memcpy(sk->src_addr, &addr.v4.sin_addr.s_addr, sizeof(addr.v4.sin_addr.s_addr));
> +		}
> +
> +		len = sizeof(addr.v4);
> +		ret = getpeername(lfd, (struct sockaddr *)&addr.v4, &len);

Same here -- connected sockets are hashed and are reported via netlink. Aren't they?

> +		if (ret) {
> +			if (errno != ENOTCONN) {
> +				pr_perror("getpeername failed on %d", p->fd);
> +				goto err;
> +			}
> +		} else {
> +			sk->dst_port = addr.v4.sin_port;
> +			memcpy(sk->dst_addr, &addr.v4.sin_addr.s_addr, sizeof(addr.v4.sin_addr.s_addr));
> +		}
> +	} else if (sk->sd.family == AF_INET6) {
> +		len = sizeof(addr.v6);
> +		ret = getsockname(lfd, (struct sockaddr *)&addr.v6, &len);
> +		if (ret) {
> +			if (errno != ENOTCONN) {
> +				pr_perror("getsockname failed on %d", p->fd);
> +				goto err;
> +			}
> +		} else {
> +			sk->src_port = addr.v6.sin6_port;
> +			memcpy(sk->src_addr, &addr.v6.sin6_addr.s6_addr, sizeof(addr.v6.sin6_addr.s6_addr));
> +		}
> +
> +		len = sizeof(addr.v6);
> +		ret = getpeername(lfd, (struct sockaddr *)&addr.v6, &len);
> +		if (ret) {
> +			if (errno != ENOTCONN) {
> +				pr_perror("getpeername failed on %d", p->fd);
> +				goto err;
> +			}
> +		} else {
> +			sk->dst_port = addr.v6.sin6_port;
> +			memcpy(sk->dst_addr, &addr.v6.sin6_addr.s6_addr, sizeof(addr.v6.sin6_addr.s6_addr));
> +		}
> +	} else
> +		BUG_ON(1);
> +
> +	return sk;
> +err:
> +	xfree(sk);
> +	return NULL;
> +}
> +



More information about the CRIU mailing list