[CRIU] [PATCH 2/2] inet: set IP_FREEBIND before binding socket to an ipv6 address
Andrew Vagin
avagin at virtuozzo.com
Thu Nov 19 06:55:39 PST 2015
On Thu, Nov 19, 2015 at 04:52:40PM +0300, Pavel Emelyanov wrote:
> On 11/19/2015 03:38 PM, Andrew Vagin wrote:
> > On Thu, Nov 19, 2015 at 03:33:37PM +0300, Pavel Emelyanov wrote:
> >> On 11/18/2015 06:58 PM, Andrey Vagin wrote:
> >>> From: Andrew Vagin <avagin at virtuozzo.com>
> >>>
> >>> When we restore ipv6 addresses, they go through a “tentative” phase
> >>> and sockets could not be bound to them in this moment.
> >>>
> >>> Reported-by: Ross Boucher <boucher at gmail.com>
> >>> Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
> >>> ---
> >>> sk-inet.c | 29 ++++++++++++++++++++++++-----
> >>> 1 file changed, 24 insertions(+), 5 deletions(-)
> >>>
> >>> diff --git a/sk-inet.c b/sk-inet.c
> >>> index 779a1bd..a973000 100644
> >>> --- a/sk-inet.c
> >>> +++ b/sk-inet.c
> >>> @@ -633,17 +633,29 @@ static int restore_sockaddr(union sockaddr_inet *sa,
> >>>
> >>> int inet_bind(int sk, struct inet_sk_info *ii)
> >>> {
> >>> + bool rst_freebind = false;
> >>> union sockaddr_inet addr;
> >>> int addr_size;
> >>> - int val;
> >>>
> >>> addr_size = restore_sockaddr(&addr, ii->ie->family,
> >>> ii->ie->src_port, ii->ie->src_addr);
> >>>
> >>> - val = 1;
> >>> - if (setsockopt(sk, SOL_IP, IP_FREEBIND, &val, sizeof(int))) {
> >>> - pr_perror("Unable to set IP_FREEBIND");
> >>> - return -1;
> >>> + /*
> >>> + * ipv6 addresses go through a “tentative” phase and
> >>> + * sockets could not be bound to them in this moment
> >>> + * without setting IP_FREEBIND.
> >>> + */
> >>> + if (ii->ie->family == AF_INET6) {
> >>> + int yes = 1;
> >>> +
> >>> + if (restore_opt(sk, SOL_IP, IP_FREEBIND, &yes))
> >>> + return -1;
> >>> +
> >>> + if (ii->ie->ip_opts && ii->ie->ip_opts->freebind)
> >>> + /* don't restore freebind in restore_ip_opts() */
> >>
> >> At all? When will it get restored then?
> >
> > We set the right value here,
>
> Where? If we're in this if branch then rst_freebin is false and we
> don't even call restore_opt() below.
we set freebind and ii->ie->ip_opts->freebind is true.
restore_ip_opts() is called for each ip socket
>
> > so we don't need to restore it in restore_ip_opts()
> >>
> >>> + ii->ie->ip_opts->has_freebind = false;
> >>> + else
> >>> + rst_freebind = true;
> >>> }
> >>>
> >>> if (bind(sk, (struct sockaddr *)&addr, addr_size) == -1) {
> >>> @@ -651,6 +663,13 @@ int inet_bind(int sk, struct inet_sk_info *ii)
> >>> return -1;
> >>> }
> >>>
> >>> + if (rst_freebind) {
> >>> + int no = 0;
> >>> +
> >>> + if (restore_opt(sk, SOL_IP, IP_FREEBIND, &no))
> >>> + return -1;
> >>
> >> Why here? Why not delay "NO" till actual options restore?
> >
> > because we restore only "yes", "no" is default.
>
> Yes, "no" is the default and you just set "no" _again_ here. Why?
because we set true and set rst_freebind to return it back
>
> >>
> >>> + }
> >>> +
> >>> return 0;
> >>> }
> >>>
> >>>
> >>
> > .
> >
>
More information about the CRIU
mailing list