LCOV - code coverage report
Current view: top level - home/snorch/criu - sockets.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 257 306 84.0 %
Date: 2014-04-22 Functions: 19 24 79.2 %
Branches: 103 179 57.5 %

           Branch data     Line data    Source code
       1                 :            : #include <unistd.h>
       2                 :            : #include <sys/socket.h>
       3                 :            : #include <linux/netlink.h>
       4                 :            : #include <linux/rtnetlink.h>
       5                 :            : #include <netinet/tcp.h>
       6                 :            : #include <errno.h>
       7                 :            : #include <linux/if.h>
       8                 :            : #include <linux/filter.h>
       9                 :            : #include <string.h>
      10                 :            : 
      11                 :            : #include "libnetlink.h"
      12                 :            : #include "sockets.h"
      13                 :            : #include "unix_diag.h"
      14                 :            : #include "inet_diag.h"
      15                 :            : #include "packet_diag.h"
      16                 :            : #include "netlink_diag.h"
      17                 :            : #include "files.h"
      18                 :            : #include "util-pie.h"
      19                 :            : #include "sk-packet.h"
      20                 :            : #include "namespaces.h"
      21                 :            : #include "net.h"
      22                 :            : #include "fs-magic.h"
      23                 :            : 
      24                 :            : #ifndef NETLINK_SOCK_DIAG
      25                 :            : #define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
      26                 :            : #endif
      27                 :            : 
      28                 :            : #ifndef SOCK_DIAG_BY_FAMILY
      29                 :            : #define SOCK_DIAG_BY_FAMILY 20
      30                 :            : #endif
      31                 :            : 
      32                 :            : #define SK_HASH_SIZE            32
      33                 :            : 
      34                 :            : #ifndef SO_GET_FILTER
      35                 :            : #define SO_GET_FILTER   SO_ATTACH_FILTER
      36                 :            : #endif
      37                 :            : 
      38                 :            : enum socket_cl_bits
      39                 :            : {
      40                 :            :         NETLINK_CL_BIT,
      41                 :            :         INET_TCP_CL_BIT,
      42                 :            :         INET_UDP_CL_BIT,
      43                 :            :         INET_UDPLITE_CL_BIT,
      44                 :            :         INET6_TCP_CL_BIT,
      45                 :            :         INET6_UDP_CL_BIT,
      46                 :            :         INET6_UDPLITE_CL_BIT,
      47                 :            :         UNIX_CL_BIT,
      48                 :            :         PACKET_CL_BIT,
      49                 :            :         _MAX_CL_BIT,
      50                 :            : };
      51                 :            : 
      52                 :            : #define MAX_CL_BIT (_MAX_CL_BIT - 1)
      53                 :            : 
      54                 :            : static DECLARE_BITMAP(socket_cl_bits, MAX_CL_BIT);
      55                 :            : 
      56                 :            : static inline
      57                 :       4364 : enum socket_cl_bits get_collect_bit_nr(unsigned int family, unsigned int proto)
      58                 :            : {
      59         [ +  + ]:       4364 :         if (family == AF_NETLINK)
      60                 :            :                 return NETLINK_CL_BIT;
      61         [ +  + ]:       3898 :         if (family == AF_UNIX)
      62                 :            :                 return UNIX_CL_BIT;
      63         [ +  + ]:       3244 :         if (family == AF_PACKET)
      64                 :            :                 return PACKET_CL_BIT;
      65         [ +  + ]:       2786 :         if (family == AF_INET) {
      66         [ +  + ]:       1410 :                 if (proto == IPPROTO_TCP)
      67                 :            :                         return INET_TCP_CL_BIT;
      68         [ +  + ]:        920 :                 if (proto == IPPROTO_UDP)
      69                 :            :                         return INET_UDP_CL_BIT;
      70         [ -  + ]:        458 :                 if (proto == IPPROTO_UDPLITE)
      71                 :            :                         return INET_UDPLITE_CL_BIT;
      72                 :            :         }
      73         [ +  - ]:       1376 :         if (family == AF_INET6) {
      74         [ +  + ]:       1376 :                 if (proto == IPPROTO_TCP)
      75                 :            :                         return INET6_TCP_CL_BIT;
      76         [ +  + ]:        908 :                 if (proto == IPPROTO_UDP)
      77                 :            :                         return INET6_UDP_CL_BIT;
      78         [ -  + ]:        450 :                 if (proto == IPPROTO_UDPLITE)
      79                 :            :                         return INET6_UDPLITE_CL_BIT;
      80                 :            :         }
      81                 :            : 
      82                 :          0 :         pr_err("Unknown pair family %d proto %d\n", family, proto);
      83                 :          0 :         BUG();
      84                 :          0 :         return -1;
      85                 :            : }
      86                 :            : 
      87                 :            : static void set_collect_bit(unsigned int family, unsigned int proto)
      88                 :            : {
      89                 :            :         enum socket_cl_bits nr;
      90                 :            : 
      91                 :       4050 :         nr = get_collect_bit_nr(family, proto);
      92                 :       4050 :         set_bit(nr, socket_cl_bits);
      93                 :            : }
      94                 :            : 
      95                 :          0 : bool socket_test_collect_bit(unsigned int family, unsigned int proto)
      96                 :            : {
      97                 :            :         enum socket_cl_bits nr;
      98                 :            : 
      99                 :        314 :         nr = get_collect_bit_nr(family, proto);
     100                 :        314 :         return test_bit(nr, socket_cl_bits) != 0;
     101                 :            : }
     102                 :            : 
     103                 :        228 : static int dump_bound_dev(int sk, SkOptsEntry *soe)
     104                 :            : {
     105                 :            :         int ret;
     106                 :            :         char dev[IFNAMSIZ];
     107                 :        228 :         socklen_t len = sizeof(dev);
     108                 :            : 
     109                 :        228 :         ret = getsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, &dev, &len);
     110         [ -  + ]:        228 :         if (ret) {
     111                 :          0 :                 pr_perror("Can't get bound dev");
     112                 :            :                 return ret;
     113                 :            :         }
     114                 :            : 
     115         [ +  + ]:        228 :         if (len == 0)
     116                 :            :                 return 0;
     117                 :            : 
     118                 :          4 :         pr_debug("\tDumping %s bound dev for sk\n", dev);
     119         [ -  + ]:          4 :         soe->so_bound_dev = xmalloc(len);
     120         [ +  - ]:          4 :         if (soe->so_bound_dev == NULL)
     121                 :            :                 return -1;
     122                 :            :         strcpy(soe->so_bound_dev, dev);
     123                 :            :         return 0;
     124                 :            : }
     125                 :            : 
     126                 :        144 : static int restore_bound_dev(int sk, SkOptsEntry *soe)
     127                 :            : {
     128                 :        144 :         char *n = soe->so_bound_dev;
     129                 :            : 
     130         [ +  + ]:        144 :         if (!n)
     131                 :            :                 return 0;
     132                 :            : 
     133                 :          2 :         pr_debug("\tBinding socket to %s dev\n", n);
     134                 :          2 :         return do_restore_opt(sk, SOL_SOCKET, SO_BINDTODEVICE, n, strlen(n));
     135                 :            : }
     136                 :            : 
     137                 :            : /*
     138                 :            :  * Protobuf handles le/be himself, but the sock_filter is not just u64,
     139                 :            :  * it's a structure and we have to preserve the fields order to be able
     140                 :            :  * to move socket image across architectures.
     141                 :            :  */
     142                 :            : 
     143                 :          4 : static void encode_filter(struct sock_filter *f, u64 *img, int n)
     144                 :            : {
     145                 :            :         int i;
     146                 :            : 
     147                 :            :         BUILD_BUG_ON(sizeof(*f) != sizeof(*img));
     148                 :            : 
     149         [ +  + ]:         60 :         for (i = 0; i < n; i++)
     150                 :        168 :                 img[i] = ((u64)f[i].code << 48) |
     151                 :        112 :                          ((u64)f[i].jt << 40) |
     152                 :        112 :                          ((u64)f[i].jf << 32) |
     153                 :         56 :                          ((u64)f[i].k << 0);
     154                 :          4 : }
     155                 :            : 
     156                 :          2 : static void decode_filter(u64 *img, struct sock_filter *f, int n)
     157                 :            : {
     158                 :            :         int i;
     159                 :            : 
     160         [ +  + ]:         30 :         for (i = 0; i < n; i++) {
     161                 :         28 :                 f[i].code = img[i] >> 48;
     162                 :         28 :                 f[i].jt = img[i] >> 40;
     163                 :         28 :                 f[i].jf = img[i] >> 32;
     164                 :         28 :                 f[i].k = img[i] >> 0;
     165                 :            :         }
     166                 :          2 : }
     167                 :            : 
     168                 :        456 : static int dump_socket_filter(int sk, SkOptsEntry *soe)
     169                 :            : {
     170                 :        228 :         socklen_t len = 0;
     171                 :            :         int ret;
     172                 :            :         struct sock_filter *flt;
     173                 :            : 
     174                 :        228 :         ret = getsockopt(sk, SOL_SOCKET, SO_GET_FILTER, NULL, &len);
     175         [ -  + ]:        228 :         if (ret) {
     176                 :          0 :                 pr_perror("Can't get socket filter len");
     177                 :            :                 return ret;
     178                 :            :         }
     179                 :            : 
     180         [ +  + ]:        228 :         if (!len) {
     181                 :        224 :                 pr_info("No filter for socket\n");
     182                 :            :                 return 0;
     183                 :            :         }
     184                 :            : 
     185         [ -  + ]:          4 :         flt = xmalloc(len * sizeof(*flt));
     186         [ +  - ]:          4 :         if (!flt)
     187                 :            :                 return -1;
     188                 :            : 
     189                 :          4 :         ret = getsockopt(sk, SOL_SOCKET, SO_GET_FILTER, flt, &len);
     190         [ -  + ]:          4 :         if (ret) {
     191                 :          0 :                 pr_perror("Can't get socket filter");
     192         [ #  # ]:          0 :                 xfree(flt);
     193                 :            :                 return ret;
     194                 :            :         }
     195                 :            : 
     196         [ -  + ]:          4 :         soe->so_filter = xmalloc(len * sizeof(*soe->so_filter));
     197         [ -  + ]:          4 :         if (!soe->so_filter) {
     198         [ #  # ]:          0 :                 xfree(flt);
     199                 :            :                 return -1;
     200                 :            :         }
     201                 :            : 
     202                 :          4 :         encode_filter(flt, soe->so_filter, len);
     203                 :          4 :         soe->n_so_filter = len;
     204         [ +  - ]:          4 :         xfree(flt);
     205                 :            :         return 0;
     206                 :            : }
     207                 :            : 
     208                 :        288 : static int restore_socket_filter(int sk, SkOptsEntry *soe)
     209                 :            : {
     210                 :            :         int ret;
     211                 :            :         struct sock_fprog sfp;
     212                 :            : 
     213         [ +  + ]:        144 :         if (!soe->n_so_filter)
     214                 :            :                 return 0;
     215                 :            : 
     216                 :          2 :         pr_info("Restoring socket filter\n");
     217                 :          2 :         sfp.len = soe->n_so_filter;
     218         [ -  + ]:          2 :         sfp.filter = xmalloc(soe->n_so_filter * sfp.len);
     219         [ +  - ]:          2 :         if (!sfp.filter)
     220                 :            :                 return -1;
     221                 :            : 
     222                 :          2 :         decode_filter(soe->so_filter, sfp.filter, sfp.len);
     223                 :          2 :         ret = restore_opt(sk, SOL_SOCKET, SO_ATTACH_FILTER, &sfp);
     224         [ +  - ]:          2 :         xfree(sfp.filter);
     225                 :            : 
     226                 :            :         return ret;
     227                 :            : }
     228                 :            : 
     229                 :            : static struct socket_desc *sockets[SK_HASH_SIZE];
     230                 :            : 
     231                 :        314 : struct socket_desc *lookup_socket(int ino, int family, int proto)
     232                 :            : {
     233                 :            :         struct socket_desc *sd;
     234                 :            : 
     235         [ -  + ]:        314 :         if (!socket_test_collect_bit(family, proto)) {
     236                 :          0 :                 pr_err("Sockets (family %d, proto %d) are not collected\n",
     237                 :            :                                                                 family, proto);
     238                 :          0 :                 return ERR_PTR(-EINVAL);
     239                 :            :         }
     240                 :            : 
     241                 :        314 :         pr_debug("\tSearching for socket %x (family %d)\n", ino, family);
     242         [ +  + ]:       2375 :         for (sd = sockets[ino % SK_HASH_SIZE]; sd; sd = sd->next)
     243         [ +  + ]:       2355 :                 if (sd->ino == ino) {
     244         [ -  + ]:        294 :                         BUG_ON(sd->family != family);
     245                 :        294 :                         return sd;
     246                 :            :                 }
     247                 :            : 
     248                 :            :         return NULL;
     249                 :            : }
     250                 :            : 
     251                 :     173166 : int sk_collect_one(int ino, int family, struct socket_desc *d)
     252                 :            : {
     253                 :            :         struct socket_desc **chain;
     254                 :            : 
     255                 :     173166 :         d->ino               = ino;
     256                 :     173166 :         d->family    = family;
     257                 :     173166 :         d->already_dumped = 0;
     258                 :            : 
     259                 :     173166 :         chain = &sockets[ino % SK_HASH_SIZE];
     260                 :     173166 :         d->next = *chain;
     261                 :     173166 :         *chain = d;
     262                 :            : 
     263                 :     173166 :         return 0;
     264                 :            : }
     265                 :            : 
     266                 :       1280 : int do_restore_opt(int sk, int level, int name, void *val, int len)
     267                 :            : {
     268         [ -  + ]:       1280 :         if (setsockopt(sk, level, name, val, len) < 0) {
     269                 :          0 :                 pr_perror("Can't set %d:%d (len %d)", level, name, len);
     270                 :          0 :                 return -1;
     271                 :            :         }
     272                 :            : 
     273                 :            :         return 0;
     274                 :            : }
     275                 :            : 
     276                 :            : /*
     277                 :            :  * Set sizes of buffers to maximum and prevent blocking
     278                 :            :  * Caller of this fn should call other socket restoring
     279                 :            :  * routines to drop the non-blocking and set proper send
     280                 :            :  * and receive buffers.
     281                 :            :  */
     282                 :         72 : int restore_prepare_socket(int sk)
     283                 :            : {
     284                 :            :         int flags;
     285                 :            : 
     286                 :            :         /* In kernel a bufsize has type int and a value is doubled. */
     287                 :         72 :         u32 maxbuf = INT_MAX / 2;
     288                 :            : 
     289         [ +  - ]:         72 :         if (restore_opt(sk, SOL_SOCKET, SO_SNDBUFFORCE, &maxbuf))
     290                 :            :                 return -1;
     291         [ +  - ]:         72 :         if (restore_opt(sk, SOL_SOCKET, SO_RCVBUFFORCE, &maxbuf))
     292                 :            :                 return -1;
     293                 :            : 
     294                 :            :         /* Prevent blocking on restore */
     295                 :         72 :         flags = fcntl(sk, F_GETFL, 0);
     296         [ -  + ]:         72 :         if (flags == -1) {
     297                 :          0 :                 pr_perror("Unable to get flags for %d", sk);
     298                 :          0 :                 return -1;
     299                 :            :         }
     300         [ -  + ]:         72 :         if (fcntl(sk, F_SETFL, flags | O_NONBLOCK) ) {
     301                 :          0 :                 pr_perror("Unable to set O_NONBLOCK for %d", sk);
     302                 :          0 :                 return -1;
     303                 :            :         }
     304                 :            : 
     305                 :            :         return 0;
     306                 :            : }
     307                 :            : 
     308                 :        144 : int restore_socket_opts(int sk, SkOptsEntry *soe)
     309                 :            : {
     310                 :            :         int ret = 0, val;
     311                 :            :         struct timeval tv;
     312                 :            : 
     313                 :        144 :         pr_info("%d restore sndbuf %d rcv buf %d\n", sk, soe->so_sndbuf, soe->so_rcvbuf);
     314                 :            : 
     315                 :            :         /* setsockopt() multiplies the input values by 2 */
     316                 :        144 :         val = soe->so_sndbuf / 2;
     317                 :        144 :         ret |= restore_opt(sk, SOL_SOCKET, SO_SNDBUFFORCE, &val);
     318                 :        144 :         val = soe->so_rcvbuf / 2;
     319                 :        144 :         ret |= restore_opt(sk, SOL_SOCKET, SO_RCVBUFFORCE, &val);
     320                 :            : 
     321         [ +  - ]:        144 :         if (soe->has_so_priority) {
     322                 :        144 :                 pr_debug("\trestore priority %d for socket\n", soe->so_priority);
     323                 :        144 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_PRIORITY, &soe->so_priority);
     324                 :            :         }
     325         [ +  - ]:        144 :         if (soe->has_so_rcvlowat) {
     326                 :        144 :                 pr_debug("\trestore rcvlowat %d for socket\n", soe->so_rcvlowat);
     327                 :        144 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_RCVLOWAT, &soe->so_rcvlowat);
     328                 :            :         }
     329         [ +  - ]:        144 :         if (soe->has_so_mark) {
     330                 :        144 :                 pr_debug("\trestore mark %d for socket\n", soe->so_mark);
     331                 :        144 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_MARK, &soe->so_mark);
     332                 :            :         }
     333 [ +  - ][ +  + ]:        144 :         if (soe->has_so_passcred && soe->so_passcred) {
     334                 :          2 :                 val = 1;
     335                 :          2 :                 pr_debug("\tset passcred for socket\n");
     336                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_PASSCRED, &val);
     337                 :            :         }
     338 [ +  - ][ +  + ]:        144 :         if (soe->has_so_passsec && soe->so_passsec) {
     339                 :          2 :                 val = 1;
     340                 :          2 :                 pr_debug("\tset passsec for socket\n");
     341                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_PASSSEC, &val);
     342                 :            :         }
     343 [ +  - ][ +  + ]:        144 :         if (soe->has_so_dontroute && soe->so_dontroute) {
     344                 :          2 :                 val = 1;
     345                 :          2 :                 pr_debug("\tset dontroute for socket\n");
     346                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_DONTROUTE, &val);
     347                 :            :         }
     348 [ +  - ][ +  + ]:        144 :         if (soe->has_so_no_check && soe->so_no_check) {
     349                 :          2 :                 val = 1;
     350                 :          2 :                 pr_debug("\tset no_check for socket\n");
     351                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_NO_CHECK, &val);
     352                 :            :         }
     353                 :            : 
     354                 :        144 :         tv.tv_sec = soe->so_snd_tmo_sec;
     355                 :        144 :         tv.tv_usec = soe->so_snd_tmo_usec;
     356                 :        144 :         ret |= restore_opt(sk, SOL_SOCKET, SO_SNDTIMEO, &tv);
     357                 :            : 
     358                 :        144 :         tv.tv_sec = soe->so_rcv_tmo_sec;
     359                 :        144 :         tv.tv_usec = soe->so_rcv_tmo_usec;
     360                 :        144 :         ret |= restore_opt(sk, SOL_SOCKET, SO_RCVTIMEO, &tv);
     361                 :            : 
     362                 :        144 :         ret |= restore_bound_dev(sk, soe);
     363                 :        144 :         ret |= restore_socket_filter(sk, soe);
     364                 :            : 
     365                 :            :         /* The restore of SO_REUSEADDR depends on type of socket */
     366                 :            : 
     367                 :        144 :         return ret;
     368                 :            : }
     369                 :            : 
     370                 :       3180 : int do_dump_opt(int sk, int level, int name, void *val, int len)
     371                 :            : {
     372                 :       3180 :         socklen_t aux = len;
     373                 :            : 
     374         [ -  + ]:       3180 :         if (getsockopt(sk, level, name, val, &aux) < 0) {
     375                 :          0 :                 pr_perror("Can't get %d:%d opt", level, name);
     376                 :          0 :                 return -1;
     377                 :            :         }
     378                 :            : 
     379         [ -  + ]:       3180 :         if (aux != len) {
     380                 :          0 :                 pr_err("Len mismatch on %d:%d : %d, want %d\n",
     381                 :            :                                 level, name, aux, len);
     382                 :          0 :                 return -1;
     383                 :            :         }
     384                 :            : 
     385                 :            :         return 0;
     386                 :            : }
     387                 :            : 
     388                 :        228 : int dump_socket_opts(int sk, SkOptsEntry *soe)
     389                 :            : {
     390                 :            :         int ret = 0, val;
     391                 :            :         struct timeval tv;
     392                 :            : 
     393                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_SNDBUF, &soe->so_sndbuf);
     394                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_RCVBUF, &soe->so_rcvbuf);
     395                 :        228 :         soe->has_so_priority = true;
     396                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_PRIORITY, &soe->so_priority);
     397                 :        228 :         soe->has_so_rcvlowat = true;
     398                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_RCVLOWAT, &soe->so_rcvlowat);
     399                 :        228 :         soe->has_so_mark = true;
     400                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_MARK, &soe->so_mark);
     401                 :            : 
     402                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_SNDTIMEO, &tv);
     403                 :        228 :         soe->so_snd_tmo_sec = tv.tv_sec;
     404                 :        228 :         soe->so_snd_tmo_usec = tv.tv_usec;
     405                 :            : 
     406                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_RCVTIMEO, &tv);
     407                 :        228 :         soe->so_rcv_tmo_sec = tv.tv_sec;
     408                 :        228 :         soe->so_rcv_tmo_usec = tv.tv_usec;
     409                 :            : 
     410                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_REUSEADDR, &val);
     411                 :        228 :         soe->reuseaddr = val ? true : false;
     412                 :        228 :         soe->has_reuseaddr = true;
     413                 :            : 
     414                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_PASSCRED, &val);
     415                 :        228 :         soe->has_so_passcred = true;
     416                 :        228 :         soe->so_passcred = val ? true : false;
     417                 :            : 
     418                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_PASSSEC, &val);
     419                 :        228 :         soe->has_so_passsec = true;
     420                 :        228 :         soe->so_passsec = val ? true : false;
     421                 :            : 
     422                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_DONTROUTE, &val);
     423                 :        228 :         soe->has_so_dontroute = true;
     424                 :        228 :         soe->so_dontroute = val ? true : false;
     425                 :            : 
     426                 :        228 :         ret |= dump_opt(sk, SOL_SOCKET, SO_NO_CHECK, &val);
     427                 :        228 :         soe->has_so_no_check = true;
     428                 :        228 :         soe->so_no_check = val ? true : false;
     429                 :            : 
     430                 :        228 :         ret |= dump_bound_dev(sk, soe);
     431                 :        228 :         ret |= dump_socket_filter(sk, soe);
     432                 :            : 
     433                 :        228 :         return ret;
     434                 :            : }
     435                 :            : 
     436                 :        212 : void release_skopts(SkOptsEntry *soe)
     437                 :            : {
     438         [ +  + ]:        212 :         xfree(soe->so_filter);
     439         [ +  + ]:        212 :         xfree(soe->so_bound_dev);
     440                 :        212 : }
     441                 :            : 
     442                 :        228 : int dump_socket(struct fd_parms *p, int lfd, const int fdinfo)
     443                 :            : {
     444                 :            :         int family;
     445                 :            :         const struct fdtype_ops *ops;
     446                 :            : 
     447         [ +  - ]:        228 :         if (dump_opt(lfd, SOL_SOCKET, SO_DOMAIN, &family))
     448                 :            :                 return -1;
     449                 :            : 
     450   [ +  +  +  +  :        228 :         switch (family) {
                   -  + ]
     451                 :            :         case AF_UNIX:
     452                 :            :                 ops = &unix_dump_ops;
     453                 :            :                 break;
     454                 :            :         case AF_INET:
     455                 :            :                 ops = &inet_dump_ops;
     456                 :         60 :                 break;
     457                 :            :         case AF_INET6:
     458                 :            :                 ops = &inet6_dump_ops;
     459                 :         26 :                 break;
     460                 :            :         case AF_PACKET:
     461                 :            :                 ops = &packet_dump_ops;
     462                 :          8 :                 break;
     463                 :            :         case AF_NETLINK:
     464                 :            :                 ops = &netlink_dump_ops;
     465                 :         16 :                 break;
     466                 :            :         default:
     467                 :          0 :                 pr_err("BUG! Unknown socket collected (family %d)\n", family);
     468                 :          0 :                 return -1;
     469                 :            :         }
     470                 :            : 
     471                 :        228 :         return do_dump_gen_file(p, lfd, ops, fdinfo);
     472                 :            : }
     473                 :            : 
     474                 :      21028 : static int inet_receive_one(struct nlmsghdr *h, void *arg)
     475                 :            : {
     476                 :            :         struct inet_diag_req_v2 *i = arg;
     477                 :            :         int type;
     478                 :            : 
     479      [ +  -  + ]:      21028 :         switch (i->sdiag_protocol) {
     480                 :            :         case IPPROTO_TCP:
     481                 :            :                 type = SOCK_STREAM;
     482                 :            :                 break;
     483                 :            :         case IPPROTO_UDP:
     484                 :            :         case IPPROTO_UDPLITE:
     485                 :            :                 type = SOCK_DGRAM;
     486                 :      10915 :                 break;
     487                 :            :         default:
     488                 :          0 :                 BUG_ON(1);
     489                 :          0 :                 return -1;
     490                 :            :         }
     491                 :            : 
     492                 :      21028 :         return inet_collect_one(h, i->sdiag_family, type);
     493                 :            : }
     494                 :            : 
     495                 :            : struct sock_diag_req {
     496                 :            :         struct nlmsghdr hdr;
     497                 :            :         union {
     498                 :            :                 struct unix_diag_req    u;
     499                 :            :                 struct inet_diag_req_v2 i;
     500                 :            :                 struct packet_diag_req  p;
     501                 :            :                 struct netlink_diag_req n;
     502                 :            :         } r;
     503                 :            : };
     504                 :            : 
     505                 :       4050 : static int do_collect_req(int nl, struct sock_diag_req *req, int size,
     506                 :            :                 int (*receive_callback)(struct nlmsghdr *h, void *), void *arg)
     507                 :            : {
     508                 :            :         int tmp;
     509                 :            : 
     510                 :       4050 :         tmp = do_rtnl_req(nl, req, size, receive_callback, arg);
     511                 :            : 
     512         [ +  - ]:       4050 :         if (tmp == 0)
     513                 :       4050 :                 set_collect_bit(req->r.n.sdiag_family, req->r.n.sdiag_protocol);
     514                 :            : 
     515                 :       4050 :         return tmp;
     516                 :            : }
     517                 :            : 
     518                 :        450 : int collect_sockets(int pid)
     519                 :            : {
     520                 :            :         int err = 0, tmp;
     521                 :        450 :         int rst = -1;
     522                 :            :         int nl;
     523                 :            :         struct sock_diag_req req;
     524                 :            : 
     525         [ +  + ]:        450 :         if (root_ns_mask & CLONE_NEWNET) {
     526                 :        214 :                 pr_info("Switching to %d's net for collecting sockets\n", pid);
     527                 :            : 
     528         [ +  - ]:        214 :                 if (switch_ns(pid, &net_ns_desc, &rst))
     529                 :            :                         return -1;
     530                 :            :         }
     531                 :            : 
     532                 :        450 :         nl = socket(PF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
     533         [ -  + ]:        450 :         if (nl < 0) {
     534                 :          0 :                 pr_perror("Can't create sock diag socket");
     535                 :            :                 err = -1;
     536                 :          0 :                 goto out;
     537                 :            :         }
     538                 :            : 
     539                 :            :         memset(&req, 0, sizeof(req));
     540                 :        450 :         req.hdr.nlmsg_len       = sizeof(req);
     541                 :        450 :         req.hdr.nlmsg_type      = SOCK_DIAG_BY_FAMILY;
     542                 :        450 :         req.hdr.nlmsg_flags     = NLM_F_DUMP | NLM_F_REQUEST;
     543                 :        450 :         req.hdr.nlmsg_seq       = CR_NLMSG_SEQ;
     544                 :            : 
     545                 :            :         /* Collect UNIX sockets */
     546                 :        450 :         req.r.u.sdiag_family    = AF_UNIX;
     547                 :        450 :         req.r.u.udiag_states    = -1; /* All */
     548                 :        450 :         req.r.u.udiag_show      = UDIAG_SHOW_NAME | UDIAG_SHOW_VFS |
     549                 :            :                                   UDIAG_SHOW_PEER | UDIAG_SHOW_ICONS |
     550                 :            :                                   UDIAG_SHOW_RQLEN;
     551                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), unix_receive_one, NULL);
     552         [ -  + ]:        450 :         if (tmp)
     553                 :            :                 err = tmp;
     554                 :            : 
     555                 :            :         /* Collect IPv4 TCP sockets */
     556                 :        450 :         req.r.i.sdiag_family    = AF_INET;
     557                 :        450 :         req.r.i.sdiag_protocol  = IPPROTO_TCP;
     558                 :        450 :         req.r.i.idiag_ext       = 0;
     559                 :            :         /* Only listening and established sockets supported yet */
     560                 :        450 :         req.r.i.idiag_states    = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
     561                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     562         [ -  + ]:        450 :         if (tmp)
     563                 :            :                 err = tmp;
     564                 :            : 
     565                 :            :         /* Collect IPv4 UDP sockets */
     566                 :        450 :         req.r.i.sdiag_family    = AF_INET;
     567                 :        450 :         req.r.i.sdiag_protocol  = IPPROTO_UDP;
     568                 :        450 :         req.r.i.idiag_ext       = 0;
     569                 :        450 :         req.r.i.idiag_states    = -1; /* All */
     570                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     571         [ -  + ]:        450 :         if (tmp)
     572                 :            :                 err = tmp;
     573                 :            : 
     574                 :            :         /* Collect IPv4 UDP-lite sockets */
     575                 :        450 :         req.r.i.sdiag_family    = AF_INET;
     576                 :        450 :         req.r.i.sdiag_protocol  = IPPROTO_UDPLITE;
     577                 :        450 :         req.r.i.idiag_ext       = 0;
     578                 :        450 :         req.r.i.idiag_states    = -1; /* All */
     579                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     580         [ -  + ]:        450 :         if (tmp)
     581                 :            :                 err = tmp;
     582                 :            : 
     583                 :            :         /* Collect IPv6 TCP sockets */
     584                 :        450 :         req.r.i.sdiag_family    = AF_INET6;
     585                 :        450 :         req.r.i.sdiag_protocol  = IPPROTO_TCP;
     586                 :        450 :         req.r.i.idiag_ext       = 0;
     587                 :            :         /* Only listening sockets supported yet */
     588                 :        450 :         req.r.i.idiag_states    = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
     589                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     590         [ -  + ]:        450 :         if (tmp)
     591                 :            :                 err = tmp;
     592                 :            : 
     593                 :            :         /* Collect IPv6 UDP sockets */
     594                 :        450 :         req.r.i.sdiag_family    = AF_INET6;
     595                 :        450 :         req.r.i.sdiag_protocol  = IPPROTO_UDP;
     596                 :        450 :         req.r.i.idiag_ext       = 0;
     597                 :        450 :         req.r.i.idiag_states    = -1; /* All */
     598                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     599         [ -  + ]:        450 :         if (tmp)
     600                 :            :                 err = tmp;
     601                 :            : 
     602                 :            :         /* Collect IPv6 UDP-lite sockets */
     603                 :        450 :         req.r.i.sdiag_family    = AF_INET6;
     604                 :        450 :         req.r.i.sdiag_protocol  = IPPROTO_UDPLITE;
     605                 :        450 :         req.r.i.idiag_ext       = 0;
     606                 :        450 :         req.r.i.idiag_states    = -1; /* All */
     607                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     608         [ -  + ]:        450 :         if (tmp)
     609                 :            :                 err = tmp;
     610                 :            : 
     611                 :        450 :         req.r.p.sdiag_family    = AF_PACKET;
     612                 :        450 :         req.r.p.sdiag_protocol  = 0;
     613                 :        450 :         req.r.p.pdiag_show      = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST |
     614                 :            :                                         PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG;
     615                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), packet_receive_one, NULL);
     616         [ -  + ]:        450 :         if (tmp) {
     617                 :          0 :                 pr_warn("The current kernel doesn't support packet_diag\n");
     618         [ #  # ]:          0 :                 if (pid == 0 || tmp != -ENOENT) /* Fedora 19 */
     619                 :            :                         err = tmp;
     620                 :            :         }
     621                 :            : 
     622                 :        450 :         req.r.n.sdiag_family    = AF_NETLINK;
     623                 :        450 :         req.r.n.sdiag_protocol  = NDIAG_PROTO_ALL;
     624                 :        450 :         req.r.n.ndiag_show      = NDIAG_SHOW_GROUPS;
     625                 :        450 :         tmp = do_collect_req(nl, &req, sizeof(req), netlink_receive_one, NULL);
     626         [ -  + ]:        450 :         if (tmp) {
     627                 :          0 :                 pr_warn("The current kernel doesn't support netlink_diag\n");
     628         [ #  # ]:          0 :                 if (pid == 0 || tmp != -ENOENT) /* Fedora 19 */
     629                 :            :                         err = tmp;
     630                 :            :         }
     631                 :            : 
     632                 :        450 :         close(nl);
     633                 :            : out:
     634         [ +  + ]:        450 :         if (rst >= 0) {
     635         [ -  + ]:        214 :                 if (restore_ns(rst, &net_ns_desc) < 0)
     636                 :            :                         err = -1;
     637         [ +  + ]:        236 :         } else if (pid != 0) {
     638                 :            :                 /*
     639                 :            :                  * If netns isn't dumped, criu will fail only
     640                 :            :                  * if an unsupported socket will be really dumped.
     641                 :            :                  */
     642                 :        234 :                 pr_info("Uncollected sockets! Will probably fail later.\n");
     643                 :            :                 err = 0;
     644                 :            :         }
     645                 :            : 
     646                 :        450 :         return err;
     647                 :            : }
     648                 :            : 
     649                 :            : static inline char *unknown(u32 val)
     650                 :            : {
     651                 :            :         static char unk[12];
     652                 :            :         snprintf(unk, sizeof(unk), "x%d", val);
     653                 :            :         return unk;
     654                 :            : }
     655                 :            : 
     656                 :          0 : char *skfamily2s(u32 f)
     657                 :            : {
     658         [ #  # ]:          0 :         if (f == AF_INET)
     659                 :            :                 return " inet";
     660         [ #  # ]:          0 :         else if (f == AF_INET6)
     661                 :            :                 return "inet6";
     662                 :            :         else
     663                 :          0 :                 return unknown(f);
     664                 :            : }
     665                 :            : 
     666                 :          0 : char *sktype2s(u32 t)
     667                 :            : {
     668         [ #  # ]:          0 :         if (t == SOCK_STREAM)
     669                 :            :                 return "stream";
     670         [ #  # ]:          0 :         else if (t == SOCK_DGRAM)
     671                 :            :                 return " dgram";
     672                 :            :         else
     673                 :          0 :                 return unknown(t);
     674                 :            : }
     675                 :            : 
     676                 :          0 : char *skproto2s(u32 p)
     677                 :            : {
     678         [ #  # ]:          0 :         if (p == IPPROTO_UDP)
     679                 :            :                 return "udp";
     680         [ #  # ]:          0 :         else if (p == IPPROTO_UDPLITE)
     681                 :            :                 return "udpl";
     682         [ #  # ]:          0 :         else if (p == IPPROTO_TCP)
     683                 :            :                 return "tcp";
     684                 :            :         else
     685                 :          0 :                 return unknown(p);
     686                 :            : }
     687                 :            : 
     688                 :          0 : char *skstate2s(u32 state)
     689                 :            : {
     690         [ #  # ]:          0 :         if (state == TCP_ESTABLISHED)
     691                 :            :                 return " estab";
     692         [ #  # ]:          0 :         else if (state == TCP_CLOSE)
     693                 :            :                 return "closed";
     694         [ #  # ]:          0 :         else if (state == TCP_LISTEN)
     695                 :            :                 return "listen";
     696                 :            :         else
     697                 :          0 :                 return unknown(state);
     698                 :            : }

Generated by: LCOV version 1.9