LCOV - code coverage report
Current view: top level - home/snorch/criu - sk-inet.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 196 245 80.0 %
Date: 2014-04-22 Functions: 17 17 100.0 %
Branches: 102 174 58.6 %

           Branch data     Line data    Source code
       1                 :            : #include <sys/types.h>
       2                 :            : #include <sys/socket.h>
       3                 :            : #include <linux/netlink.h>
       4                 :            : #include <linux/rtnetlink.h>
       5                 :            : #include <sys/mman.h>
       6                 :            : #include <unistd.h>
       7                 :            : #include <netinet/tcp.h>
       8                 :            : #include <arpa/inet.h>
       9                 :            : #include <string.h>
      10                 :            : #include <stdlib.h>
      11                 :            : 
      12                 :            : #include "asm/types.h"
      13                 :            : #include "libnetlink.h"
      14                 :            : #include "cr_options.h"
      15                 :            : #include "fdset.h"
      16                 :            : #include "inet_diag.h"
      17                 :            : #include "files.h"
      18                 :            : #include "image.h"
      19                 :            : #include "log.h"
      20                 :            : #include "util.h"
      21                 :            : #include "sockets.h"
      22                 :            : #include "sk-inet.h"
      23                 :            : 
      24                 :            : #define PB_ALEN_INET    1
      25                 :            : #define PB_ALEN_INET6   4
      26                 :            : 
      27                 :            : static LIST_HEAD(inet_ports);
      28                 :            : 
      29                 :            : struct inet_port {
      30                 :            :         int port;
      31                 :            :         int type;
      32                 :            :         futex_t users;
      33                 :            :         struct list_head list;
      34                 :            : };
      35                 :            : 
      36                 :        182 : static struct inet_port *port_add(int type, int port)
      37                 :            : {
      38                 :            :         struct inet_port *e;
      39                 :            : 
      40         [ +  + ]:        224 :         list_for_each_entry(e, &inet_ports, list)
      41 [ +  - ][ +  + ]:         86 :                 if (e->type == type && e->port == port) {
      42                 :            :                         futex_inc(&e->users);
      43                 :         44 :                         return e;
      44                 :            :                 }
      45                 :            : 
      46                 :        138 :         e = shmalloc(sizeof(*e));
      47         [ -  + ]:        138 :         if (e == NULL) {
      48                 :          0 :                 pr_err("Not enough memory\n");
      49                 :          0 :                 return NULL;
      50                 :            :         }
      51                 :            : 
      52                 :        138 :         e->port = port;
      53                 :        138 :         e->type = type;
      54                 :            :         futex_init(&e->users);
      55                 :            :         futex_inc(&e->users);
      56                 :            : 
      57                 :        138 :         list_add(&e->list, &inet_ports);
      58                 :            : 
      59                 :        138 :         return e;
      60                 :            : }
      61                 :            : 
      62                 :      21114 : static void show_one_inet(const char *act, const struct inet_sk_desc *sk)
      63                 :            : {
      64                 :      21114 :         char src_addr[INET_ADDR_LEN] = "<unknown>";
      65                 :            : 
      66         [ -  + ]:      21114 :         if (inet_ntop(sk->sd.family, (void *)sk->src_addr, src_addr,
      67                 :            :                       INET_ADDR_LEN) == NULL) {
      68                 :          0 :                 pr_perror("Failed to translate address");
      69                 :            :         }
      70                 :            : 
      71                 :      21114 :         pr_debug("\t%s: ino 0x%8x family %4d type %4d port %8d "
      72                 :            :                 "state %2d src_addr %s\n",
      73                 :            :                 act, sk->sd.ino, sk->sd.family, sk->type, sk->src_port,
      74                 :            :                 sk->state, src_addr);
      75                 :      21114 : }
      76                 :            : 
      77                 :        148 : static void show_one_inet_img(const char *act, const InetSkEntry *e)
      78                 :            : {
      79                 :        148 :         char src_addr[INET_ADDR_LEN] = "<unknown>";
      80                 :            : 
      81         [ -  + ]:        148 :         if (inet_ntop(e->family, (void *)e->src_addr, src_addr,
      82                 :            :                       INET_ADDR_LEN) == NULL) {
      83                 :          0 :                 pr_perror("Failed to translate address");
      84                 :            :         }
      85                 :            : 
      86                 :        148 :         pr_debug("\t%s: family %d type %d proto %d port %d "
      87                 :            :                 "state %d src_addr %s\n",
      88                 :            :                 act, e->family, e->type, e->proto, e->src_port,
      89                 :            :                 e->state, src_addr);
      90                 :        148 : }
      91                 :            : 
      92                 :         86 : static int can_dump_inet_sk(const struct inet_sk_desc *sk, int proto)
      93                 :            : {
      94         [ -  + ]:         86 :         BUG_ON((sk->sd.family != AF_INET) && (sk->sd.family != AF_INET6));
      95                 :            : 
      96         [ -  + ]:         86 :         if (sk->shutdown) {
      97                 :          0 :                 pr_err("Can't dump shutdown inet socket %x\n",
      98                 :            :                                 sk->sd.ino);
      99                 :          0 :                 return 0;
     100                 :            :         }
     101                 :            : 
     102         [ +  + ]:         86 :         if (sk->type == SOCK_DGRAM) {
     103         [ -  + ]:         28 :                 if (sk->wqlen != 0) {
     104                 :          0 :                         pr_err("Can't dump corked dgram socket %x\n",
     105                 :            :                                         sk->sd.ino);
     106                 :          0 :                         return 0;
     107                 :            :                 }
     108                 :            : 
     109         [ -  + ]:         28 :                 if (sk->rqlen)
     110                 :          0 :                         pr_warn("Read queue is dropped for socket %x\n",
     111                 :            :                                         sk->sd.ino);
     112                 :            : 
     113                 :            :                 return 1;
     114                 :            :         }
     115                 :            : 
     116         [ -  + ]:         58 :         if (sk->type != SOCK_STREAM) {
     117                 :          0 :                 pr_err("Can't dump %d inet socket %x. "
     118                 :            :                                 "Only can stream and dgram.\n",
     119                 :            :                                 sk->type, sk->sd.ino);
     120                 :          0 :                 return 0;
     121                 :            :         }
     122                 :            : 
     123   [ +  +  -  + ]:         58 :         switch (sk->state) {
     124                 :            :         case TCP_LISTEN:
     125         [ -  + ]:         22 :                 if (sk->rqlen != 0) {
     126                 :            :                         /*
     127                 :            :                          * Currently the ICONS nla reports the conn
     128                 :            :                          * requests for listen sockets. Need to pick
     129                 :            :                          * those up and fix the connect job respectively
     130                 :            :                          */
     131                 :          0 :                         pr_err("In-flight connection (l) for %x\n",
     132                 :            :                                         sk->sd.ino);
     133                 :          0 :                         return 0;
     134                 :            :                 }
     135                 :            :                 break;
     136                 :            :         case TCP_ESTABLISHED:
     137         [ -  + ]:         24 :                 if (!opts.tcp_established_ok) {
     138                 :          0 :                         pr_err("Connected TCP socket, consider using %s option.\n",
     139                 :            :                                         SK_EST_PARAM);
     140                 :          0 :                         return 0;
     141                 :            :                 }
     142                 :            :                 break;
     143                 :            :         case TCP_CLOSE:
     144                 :            :                 /* Trivial case, we just need to create a socket on restore */
     145                 :            :                 break;
     146                 :            :         default:
     147                 :          0 :                 pr_err("Unknown inet socket %x state %d\n", sk->sd.ino, sk->state);
     148                 :          0 :                 return 0;
     149                 :            :         }
     150                 :            : 
     151                 :            :         /* Make sure it's a proto we support */
     152         [ -  + ]:         58 :         switch (proto) {
     153                 :            :         case IPPROTO_IP:
     154                 :            :         case IPPROTO_TCP:
     155                 :            :         case IPPROTO_UDP:
     156                 :            :         case IPPROTO_UDPLITE:
     157                 :            :                 break;
     158                 :            :         default:
     159                 :          0 :                 pr_err("Unsupported proto %d for socket %x\n", proto, sk->sd.ino);
     160                 :          0 :                 return 0;
     161                 :            :         }
     162                 :            : 
     163                 :            :         return 1;
     164                 :            : }
     165                 :            : 
     166                 :         16 : static struct inet_sk_desc *gen_uncon_sk(int lfd, const struct fd_parms *p, int proto)
     167                 :            : {
     168                 :            :         struct inet_sk_desc *sk;
     169                 :            :         char address;
     170                 :            :         socklen_t aux;
     171                 :            :         int ret;
     172                 :            : 
     173         [ -  + ]:         16 :         sk = xzalloc(sizeof(*sk));
     174         [ +  - ]:         16 :         if (!sk)
     175                 :            :                 goto err;
     176                 :            : 
     177                 :            :         /* It should has no peer name */
     178                 :         16 :         aux = sizeof(address);
     179                 :         16 :         ret = getsockopt(lfd, SOL_SOCKET, SO_PEERNAME, &address, &aux);
     180         [ +  - ]:         16 :         if (ret < 0) {
     181         [ -  + ]:         16 :                 if (errno != ENOTCONN) {
     182                 :          0 :                         pr_perror("Unexpected error returned from unconnected socket");
     183                 :            :                         goto err;
     184                 :            :                 }
     185         [ #  # ]:          0 :         } else if (ret == 0) {
     186                 :          0 :                 pr_err("Name resolved on unconnected socket\n");
     187                 :            :                 goto err;
     188                 :            :         }
     189                 :            : 
     190                 :         16 :         sk->sd.ino = p->stat.st_ino;
     191                 :            : 
     192                 :         16 :         ret  = do_dump_opt(lfd, SOL_SOCKET, SO_DOMAIN, &sk->sd.family, sizeof(sk->sd.family));
     193                 :         16 :         ret |= do_dump_opt(lfd, SOL_SOCKET, SO_TYPE, &sk->type, sizeof(sk->type));
     194         [ +  - ]:         16 :         if (ret)
     195                 :            :                 goto err;
     196                 :            : 
     197         [ +  + ]:         16 :         if (proto == IPPROTO_TCP) {
     198                 :            :                 struct tcp_info info;
     199                 :            : 
     200                 :         12 :                 aux = sizeof(info);
     201                 :         12 :                 ret = getsockopt(lfd, SOL_TCP, TCP_INFO, &info, &aux);
     202         [ -  + ]:         12 :                 if (ret) {
     203                 :          0 :                         pr_perror("Failed to obtain TCP_INFO");
     204                 :          0 :                         goto err;
     205                 :            :                 }
     206                 :            : 
     207         [ -  + ]:         12 :                 if (info.tcpi_state != TCP_CLOSE) {
     208                 :          0 :                         pr_err("Socket state %d obtained but expected %d\n",
     209                 :            :                                info.tcpi_state, TCP_CLOSE);
     210                 :            :                         goto err;
     211                 :            :                 }
     212                 :            : 
     213                 :         12 :                 sk->wqlen = info.tcpi_backoff;
     214                 :            :         }
     215                 :            : 
     216                 :         16 :         sk->state = TCP_CLOSE;
     217                 :            : 
     218                 :         16 :         sk_collect_one(sk->sd.ino, sk->sd.family, &sk->sd);
     219                 :            : 
     220                 :            :         return sk;
     221                 :            : err:
     222         [ #  # ]:          0 :         xfree(sk);
     223                 :            :         return NULL;
     224                 :            : }
     225                 :            : 
     226                 :         86 : static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int family)
     227                 :            : {
     228                 :            :         struct inet_sk_desc *sk;
     229                 :         86 :         InetSkEntry ie = INET_SK_ENTRY__INIT;
     230                 :         86 :         SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
     231                 :            :         int ret = -1, err = -1, proto;
     232                 :            : 
     233                 :         86 :         ret = do_dump_opt(lfd, SOL_SOCKET, SO_PROTOCOL,
     234                 :            :                                         &proto, sizeof(proto));
     235         [ +  - ]:         86 :         if (ret)
     236                 :            :                 goto err;
     237                 :            : 
     238                 :         86 :         sk = (struct inet_sk_desc *)lookup_socket(p->stat.st_ino, family, proto);
     239         [ +  - ]:         86 :         if (IS_ERR(sk))
     240                 :            :                 goto err;
     241         [ +  + ]:         86 :         if (!sk) {
     242                 :         16 :                 sk = gen_uncon_sk(lfd, p, proto);
     243         [ +  - ]:         16 :                 if (!sk)
     244                 :            :                         goto err;
     245                 :            :         }
     246                 :            : 
     247         [ +  - ]:         86 :         if (!can_dump_inet_sk(sk, proto))
     248                 :            :                 goto err;
     249                 :            : 
     250         [ -  + ]:         86 :         BUG_ON(sk->sd.already_dumped);
     251                 :            : 
     252                 :         86 :         ie.id           = id;
     253                 :         86 :         ie.ino          = sk->sd.ino;
     254                 :         86 :         ie.family       = family;
     255                 :         86 :         ie.proto        = proto;
     256                 :         86 :         ie.type         = sk->type;
     257                 :         86 :         ie.state        = sk->state;
     258                 :         86 :         ie.src_port     = sk->src_port;
     259                 :         86 :         ie.dst_port     = sk->dst_port;
     260                 :         86 :         ie.backlog      = sk->wqlen;
     261                 :         86 :         ie.flags        = p->flags;
     262                 :            : 
     263                 :         86 :         ie.fown         = (FownEntry *)&p->fown;
     264                 :         86 :         ie.opts         = &skopts;
     265                 :            : 
     266                 :         86 :         ie.n_src_addr = PB_ALEN_INET;
     267                 :         86 :         ie.n_dst_addr = PB_ALEN_INET;
     268         [ +  + ]:         86 :         if (ie.family == AF_INET6) {
     269                 :            :                 int val;
     270                 :            : 
     271                 :         26 :                 ie.n_src_addr = PB_ALEN_INET6;
     272                 :         26 :                 ie.n_dst_addr = PB_ALEN_INET6;
     273                 :            : 
     274                 :         26 :                 ret = dump_opt(lfd, SOL_IPV6, IPV6_V6ONLY, &val);
     275         [ +  - ]:         26 :                 if (ret < 0)
     276                 :            :                         goto err;
     277                 :            : 
     278                 :         26 :                 ie.v6only = val ? true : false;
     279                 :         26 :                 ie.has_v6only = true;
     280                 :            :         }
     281                 :            : 
     282         [ -  + ]:         86 :         ie.src_addr = xmalloc(pb_repeated_size(&ie, src_addr));
     283         [ -  + ]:         86 :         ie.dst_addr = xmalloc(pb_repeated_size(&ie, dst_addr));
     284                 :            : 
     285 [ +  - ][ +  - ]:         86 :         if (!ie.src_addr || !ie.dst_addr)
     286                 :            :                 goto err;
     287                 :            : 
     288                 :         86 :         memcpy(ie.src_addr, sk->src_addr, pb_repeated_size(&ie, src_addr));
     289                 :         86 :         memcpy(ie.dst_addr, sk->dst_addr, pb_repeated_size(&ie, dst_addr));
     290                 :            : 
     291         [ +  - ]:         86 :         if (dump_socket_opts(lfd, &skopts))
     292                 :            :                 goto err;
     293                 :            : 
     294         [ +  - ]:         86 :         if (pb_write_one(fdset_fd(glob_fdset, CR_FD_INETSK), &ie, PB_INET_SK))
     295                 :            :                 goto err;
     296                 :            : 
     297                 :         86 :         pr_info("Dumping inet socket at %d\n", p->fd);
     298                 :         86 :         show_one_inet("Dumping", sk);
     299                 :         86 :         show_one_inet_img("Dumped", &ie);
     300                 :         86 :         sk->sd.already_dumped = 1;
     301                 :         86 :         sk->cpt_reuseaddr = skopts.reuseaddr;
     302                 :            : 
     303         [ +  + ]:         86 :         switch (proto) {
     304                 :            :         case IPPROTO_TCP:
     305                 :         58 :                 err = dump_one_tcp(lfd, sk);
     306                 :         58 :                 break;
     307                 :            :         default:
     308                 :            :                 err = 0;
     309                 :            :                 break;
     310                 :            :         }
     311                 :            : err:
     312                 :         86 :         release_skopts(&skopts);
     313         [ +  - ]:         86 :         xfree(ie.src_addr);
     314         [ +  - ]:         86 :         xfree(ie.dst_addr);
     315                 :         86 :         return err;
     316                 :            : }
     317                 :            : 
     318                 :         60 : static int dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p)
     319                 :            : {
     320                 :         60 :         return do_dump_one_inet_fd(lfd, id, p, PF_INET);
     321                 :            : }
     322                 :            : 
     323                 :            : const struct fdtype_ops inet_dump_ops = {
     324                 :            :         .type           = FD_TYPES__INETSK,
     325                 :            :         .dump           = dump_one_inet_fd,
     326                 :            : };
     327                 :            : 
     328                 :         26 : static int dump_one_inet6_fd(int lfd, u32 id, const struct fd_parms *p)
     329                 :            : {
     330                 :         26 :         return do_dump_one_inet_fd(lfd, id, p, PF_INET6);
     331                 :            : }
     332                 :            : 
     333                 :            : const struct fdtype_ops inet6_dump_ops = {
     334                 :            :         .type           = FD_TYPES__INETSK,
     335                 :            :         .dump           = dump_one_inet6_fd,
     336                 :            : };
     337                 :            : 
     338                 :      21028 : int inet_collect_one(struct nlmsghdr *h, int family, int type)
     339                 :            : {
     340                 :            :         struct inet_sk_desc *d;
     341                 :            :         struct inet_diag_msg *m = NLMSG_DATA(h);
     342                 :            :         struct rtattr *tb[INET_DIAG_MAX+1];
     343                 :            :         int ret;
     344                 :            : 
     345                 :      21028 :         parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(m + 1),
     346                 :      21028 :                      h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
     347                 :            : 
     348         [ -  + ]:      21028 :         d = xzalloc(sizeof(*d));
     349         [ +  - ]:      21028 :         if (!d)
     350                 :            :                 return -1;
     351                 :            : 
     352                 :      21028 :         d->type = type;
     353         [ -  + ]:      21028 :         d->src_port = ntohs(m->id.idiag_sport);
     354         [ -  + ]:      21028 :         d->dst_port = ntohs(m->id.idiag_dport);
     355                 :      21028 :         d->state = m->idiag_state;
     356                 :      21028 :         d->rqlen = m->idiag_rqueue;
     357                 :      21028 :         d->wqlen = m->idiag_wqueue;
     358                 :      21028 :         memcpy(d->src_addr, m->id.idiag_src, sizeof(u32) * 4);
     359                 :      21028 :         memcpy(d->dst_addr, m->id.idiag_dst, sizeof(u32) * 4);
     360                 :            : 
     361         [ +  - ]:      21028 :         if (tb[INET_DIAG_SHUTDOWN])
     362                 :      21028 :                 d->shutdown = *(u8 *)RTA_DATA(tb[INET_DIAG_SHUTDOWN]);
     363                 :            :         else
     364         [ #  # ]:          0 :                 pr_err_once("Can't check shutdown state of inet socket\n");
     365                 :            : 
     366                 :      21028 :         ret = sk_collect_one(m->idiag_inode, family, &d->sd);
     367                 :            : 
     368                 :      21028 :         show_one_inet("Collected", d);
     369                 :            : 
     370                 :      21028 :         return ret;
     371                 :            : }
     372                 :            : 
     373                 :            : static int open_inet_sk(struct file_desc *d);
     374                 :            : static int post_open_inet_sk(struct file_desc *d, int sk);
     375                 :            : 
     376                 :            : static struct file_desc_ops inet_desc_ops = {
     377                 :            :         .type = FD_TYPES__INETSK,
     378                 :            :         .open = open_inet_sk,
     379                 :            :         .post_open = post_open_inet_sk,
     380                 :            : };
     381                 :            : 
     382                 :            : static inline int tcp_connection(InetSkEntry *ie)
     383                 :            : {
     384                 :        306 :         return (ie->proto == IPPROTO_TCP) && (ie->state == TCP_ESTABLISHED);
     385                 :            : }
     386                 :            : 
     387                 :        182 : static int collect_one_inetsk(void *o, ProtobufCMessage *base)
     388                 :            : {
     389                 :            :         struct inet_sk_info *ii = o;
     390                 :            : 
     391                 :        182 :         ii->ie = pb_msg(base, InetSkEntry);
     392         [ +  + ]:        182 :         if (tcp_connection(ii->ie))
     393                 :         56 :                 tcp_locked_conn_add(ii);
     394                 :            : 
     395                 :            :         /*
     396                 :            :          * A socket can reuse addr only if all previous sockets allow that,
     397                 :            :          * so a value of SO_REUSEADDR can be restored after restoring all
     398                 :            :          * sockets.
     399                 :            :          */
     400                 :        182 :         ii->port = port_add(ii->ie->type, ii->ie->src_port);
     401         [ +  - ]:        182 :         if (ii->port == NULL)
     402                 :            :                 return -1;
     403                 :            : 
     404                 :        182 :         return file_desc_add(&ii->d, ii->ie->id, &inet_desc_ops);
     405                 :            : }
     406                 :            : 
     407                 :            : struct collect_image_info inet_sk_cinfo = {
     408                 :            :         .fd_type = CR_FD_INETSK,
     409                 :            :         .pb_type = PB_INET_SK,
     410                 :            :         .priv_size = sizeof(struct inet_sk_info),
     411                 :            :         .collect = collect_one_inetsk,
     412                 :            : };
     413                 :            : 
     414                 :       1012 : int collect_inet_sockets(void)
     415                 :            : {
     416                 :       1012 :         return collect_image(&inet_sk_cinfo);
     417                 :            : }
     418                 :            : 
     419                 :         62 : static int inet_validate_address(InetSkEntry *ie)
     420                 :            : {
     421 [ +  + ][ +  - ]:         62 :         if ((ie->family == AF_INET) &&
     422                 :            :                         /* v0.1 had 4 in ipv4 addr len */
     423         [ -  + ]:         42 :                         (ie->n_src_addr >= PB_ALEN_INET) &&
     424                 :         42 :                         (ie->n_dst_addr >= PB_ALEN_INET))
     425                 :            :                 return 0;
     426                 :            : 
     427 [ +  - ][ +  - ]:         20 :         if ((ie->family == AF_INET6) &&
     428         [ -  + ]:         20 :                         (ie->n_src_addr == PB_ALEN_INET6) &&
     429                 :         20 :                         (ie->n_dst_addr == PB_ALEN_INET6))
     430                 :            :                 return 0;
     431                 :            : 
     432                 :          0 :         pr_err("Addr len mismatch f %d ss %zu ds %zu\n", ie->family,
     433                 :            :                         pb_repeated_size(ie, src_addr),
     434                 :            :                         pb_repeated_size(ie, dst_addr));
     435                 :            : 
     436                 :          0 :         return -1;
     437                 :            : }
     438                 :            : 
     439                 :         62 : static int post_open_inet_sk(struct file_desc *d, int sk)
     440                 :            : {
     441                 :            :         struct inet_sk_info *ii;
     442                 :            :         int val;
     443                 :            : 
     444                 :            :         ii = container_of(d, struct inet_sk_info, d);
     445                 :            : 
     446                 :            :         /*
     447                 :            :          * TCP sockets are handled at the last moment
     448                 :            :          * after unlocking connections.
     449                 :            :          */
     450         [ +  + ]:         62 :         if (tcp_connection(ii->ie)) {
     451         [ +  - ]:         24 :                 if (rst_tcp_socks_add(sk, ii->ie->opts->reuseaddr))
     452                 :            :                         return -1;
     453                 :            : 
     454                 :         24 :                 return 0;
     455                 :            :         }
     456                 :            : 
     457                 :            :         /* SO_REUSEADDR is set for all sockets */
     458         [ +  + ]:         38 :         if (ii->ie->opts->reuseaddr)
     459                 :            :                 return 0;
     460                 :            : 
     461                 :         20 :         futex_wait_until(&ii->port->users, 0);
     462                 :            : 
     463                 :         20 :         val = ii->ie->opts->reuseaddr;
     464         [ +  - ]:         20 :         if (restore_opt(sk, SOL_SOCKET, SO_REUSEADDR, &val))
     465                 :            :                 return -1;
     466                 :            : 
     467                 :         20 :         return 0;
     468                 :            : }
     469                 :            : 
     470                 :         62 : static int open_inet_sk(struct file_desc *d)
     471                 :            : {
     472                 :            :         struct inet_sk_info *ii;
     473                 :            :         InetSkEntry *ie;
     474                 :         62 :         int sk, yes = 1;
     475                 :            : 
     476                 :         62 :         ii = container_of(d, struct inet_sk_info, d);
     477                 :         62 :         ie = ii->ie;
     478                 :            : 
     479                 :         62 :         show_one_inet_img("Restore", ie);
     480                 :            : 
     481         [ -  + ]:         62 :         if (ie->family != AF_INET && ie->family != AF_INET6) {
     482                 :          0 :                 pr_err("Unsupported socket family: %d\n", ie->family);
     483                 :          0 :                 return -1;
     484                 :            :         }
     485                 :            : 
     486         [ -  + ]:         62 :         if ((ie->type != SOCK_STREAM) && (ie->type != SOCK_DGRAM)) {
     487                 :          0 :                 pr_err("Unsupported socket type: %d\n", ie->type);
     488                 :          0 :                 return -1;
     489                 :            :         }
     490                 :            : 
     491         [ +  - ]:         62 :         if (inet_validate_address(ie))
     492                 :            :                 return -1;
     493                 :            : 
     494                 :         62 :         sk = socket(ie->family, ie->type, ie->proto);
     495         [ -  + ]:         62 :         if (sk < 0) {
     496                 :          0 :                 pr_perror("Can't create inet socket");
     497                 :          0 :                 return -1;
     498                 :            :         }
     499                 :            : 
     500         [ +  + ]:         62 :         if (ie->v6only) {
     501         [ +  - ]:          4 :                 if (restore_opt(sk, SOL_IPV6, IPV6_V6ONLY, &yes) == -1)
     502                 :            :                         return -1;
     503                 :            :         }
     504                 :            : 
     505                 :            :         /*
     506                 :            :          * Set SO_REUSEADDR, because some sockets can be bound to one addr.
     507                 :            :          * The origin value of SO_REUSEADDR will be restored in post_open.
     508                 :            :          */
     509         [ +  - ]:         62 :         if (restore_opt(sk, SOL_SOCKET, SO_REUSEADDR, &yes))
     510                 :            :                 return -1;
     511                 :            : 
     512         [ +  + ]:         62 :         if (tcp_connection(ie)) {
     513         [ -  + ]:         24 :                 if (!opts.tcp_established_ok) {
     514                 :          0 :                         pr_err("Connected TCP socket in image\n");
     515                 :          0 :                         goto err;
     516                 :            :                 }
     517                 :            : 
     518         [ +  - ]:         24 :                 if (restore_one_tcp(sk, ii))
     519                 :            :                         goto err;
     520                 :            : 
     521                 :            :                 goto done;
     522                 :            :         }
     523                 :            : 
     524                 :            :         /*
     525                 :            :          * Listen sockets are easiest ones -- simply
     526                 :            :          * bind() and listen(), and that's all.
     527                 :            :          */
     528                 :            : 
     529         [ +  + ]:         38 :         if (ie->src_port) {
     530         [ +  - ]:         30 :                 if (inet_bind(sk, ii))
     531                 :            :                         goto err;
     532                 :            :         }
     533                 :            : 
     534         [ +  + ]:         38 :         if (ie->state == TCP_LISTEN) {
     535         [ -  + ]:         18 :                 if (ie->proto != IPPROTO_TCP) {
     536                 :          0 :                         pr_err("Wrong socket in listen state %d\n", ie->proto);
     537                 :          0 :                         goto err;
     538                 :            :                 }
     539                 :            : 
     540         [ -  + ]:         18 :                 if (listen(sk, ie->backlog) == -1) {
     541                 :          0 :                         pr_perror("Can't listen on a socket");
     542                 :          0 :                         goto err;
     543                 :            :                 }
     544                 :            :         }
     545                 :            : 
     546   [ +  +  +  - ]:         44 :         if (ie->state == TCP_ESTABLISHED &&
     547                 :          6 :                         inet_connect(sk, ii))
     548                 :            :                 goto err;
     549                 :            : done:
     550                 :         62 :         futex_dec(&ii->port->users);
     551                 :            : 
     552         [ +  - ]:         62 :         if (rst_file_params(sk, ie->fown, ie->flags))
     553                 :            :                 goto err;
     554                 :            : 
     555         [ +  - ]:         62 :         if (restore_socket_opts(sk, ie->opts))
     556                 :            :                 return -1;
     557                 :            : 
     558                 :         62 :         return sk;
     559                 :            : 
     560                 :            : err:
     561                 :          0 :         close(sk);
     562                 :          0 :         return -1;
     563                 :            : }
     564                 :            : 
     565                 :            : union sockaddr_inet {
     566                 :            :         struct sockaddr_in v4;
     567                 :            :         struct sockaddr_in6 v6;
     568                 :            : };
     569                 :            : 
     570                 :         84 : static int restore_sockaddr(union sockaddr_inet *sa,
     571                 :            :                 int family, u32 pb_port, u32 *pb_addr)
     572                 :            : {
     573                 :            :         BUILD_BUG_ON(sizeof(sa->v4.sin_addr.s_addr) > PB_ALEN_INET * sizeof(u32));
     574                 :            :         BUILD_BUG_ON(sizeof(sa->v6.sin6_addr.s6_addr) > PB_ALEN_INET6 * sizeof(u32));
     575                 :            : 
     576                 :            :         memzero(sa, sizeof(*sa));
     577                 :            : 
     578         [ +  + ]:         84 :         if (family == AF_INET) {
     579                 :         54 :                 sa->v4.sin_family = AF_INET;
     580         [ -  + ]:         54 :                 sa->v4.sin_port = htons(pb_port);
     581                 :         54 :                 memcpy(&sa->v4.sin_addr.s_addr, pb_addr, sizeof(sa->v4.sin_addr.s_addr));
     582                 :         54 :                 return sizeof(sa->v4);
     583                 :            :         }
     584                 :            : 
     585         [ +  - ]:         30 :         if (family == AF_INET6) {
     586                 :         30 :                 sa->v6.sin6_family = AF_INET6;
     587         [ -  + ]:         30 :                 sa->v6.sin6_port = htons(pb_port);
     588                 :         30 :                 memcpy(sa->v6.sin6_addr.s6_addr, pb_addr, sizeof(sa->v6.sin6_addr.s6_addr));
     589                 :         30 :                 return sizeof(sa->v6);
     590                 :            :         }
     591                 :            : 
     592                 :          0 :         BUG();
     593                 :          0 :         return -1;
     594                 :            : }
     595                 :            : 
     596                 :         54 : int inet_bind(int sk, struct inet_sk_info *ii)
     597                 :            : {
     598                 :            :         union sockaddr_inet addr;
     599                 :            :         int addr_size;
     600                 :            : 
     601                 :         54 :         addr_size = restore_sockaddr(&addr, ii->ie->family,
     602                 :         54 :                         ii->ie->src_port, ii->ie->src_addr);
     603                 :            : 
     604         [ -  + ]:         54 :         if (bind(sk, (struct sockaddr *)&addr, addr_size) == -1) {
     605                 :          0 :                 pr_perror("Can't bind inet socket");
     606                 :          0 :                 return -1;
     607                 :            :         }
     608                 :            : 
     609                 :            :         return 0;
     610                 :            : }
     611                 :            : 
     612                 :         30 : int inet_connect(int sk, struct inet_sk_info *ii)
     613                 :            : {
     614                 :            :         union sockaddr_inet addr;
     615                 :            :         int addr_size;
     616                 :            : 
     617                 :         30 :         addr_size = restore_sockaddr(&addr, ii->ie->family,
     618                 :         30 :                         ii->ie->dst_port, ii->ie->dst_addr);
     619                 :            : 
     620         [ -  + ]:         30 :         if (connect(sk, (struct sockaddr *)&addr, addr_size) == -1) {
     621                 :          0 :                 pr_perror("Can't connect inet socket back");
     622                 :          0 :                 return -1;
     623                 :            :         }
     624                 :            : 
     625                 :            :         return 0;
     626                 :            : }

Generated by: LCOV version 1.9