LCOV - code coverage report
Current view: top level - crtools - sockets.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 235 277 84.8 %
Date: 2012-12-28 Functions: 17 22 77.3 %
Branches: 77 142 54.2 %

           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 "files.h"
      17                 :            : #include "util-net.h"
      18                 :            : #include "sk-packet.h"
      19                 :            : #include "namespaces.h"
      20                 :            : #include "crtools.h"
      21                 :            : #include "net.h"
      22                 :            : 
      23                 :            : #ifndef NETLINK_SOCK_DIAG
      24                 :            : #define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
      25                 :            : #endif
      26                 :            : 
      27                 :            : #ifndef SOCK_DIAG_BY_FAMILY
      28                 :            : #define SOCK_DIAG_BY_FAMILY 20
      29                 :            : #endif
      30                 :            : 
      31                 :            : #ifndef SOCKFS_MAGIC
      32                 :            : #define SOCKFS_MAGIC    0x534F434B
      33                 :            : #endif
      34                 :            : 
      35                 :            : #define SK_HASH_SIZE            32
      36                 :            : 
      37                 :            : #ifndef SO_GET_FILTER
      38                 :            : #define SO_GET_FILTER   SO_ATTACH_FILTER
      39                 :            : #endif
      40                 :            : 
      41                 :         99 : static int dump_bound_dev(int sk, SkOptsEntry *soe)
      42                 :            : {
      43                 :            :         int ret;
      44                 :            :         char dev[IFNAMSIZ];
      45                 :         99 :         socklen_t len = sizeof(dev);
      46                 :            : 
      47                 :         99 :         ret = getsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, &dev, &len);
      48         [ -  + ]:         99 :         if (ret) {
      49         [ #  # ]:          0 :                 if (errno == ENOPROTOOPT) {
      50                 :          0 :                         pr_warn("Bound device may be missing for socket\n");
      51                 :            :                         return 0;
      52                 :            :                 }
      53                 :            : 
      54                 :          0 :                 pr_perror("Can't get bound dev");
      55                 :            :                 return ret;
      56                 :            :         }
      57                 :            : 
      58         [ +  + ]:         99 :         if (len == 0)
      59                 :            :                 return 0;
      60                 :            : 
      61                 :          2 :         pr_debug("\tDumping %s bound dev for sk\n", dev);
      62         [ -  + ]:          2 :         soe->so_bound_dev = xmalloc(len);
      63                 :         99 :         strcpy(soe->so_bound_dev, dev);
      64                 :            :         return 0;
      65                 :            : }
      66                 :            : 
      67                 :        108 : static int restore_bound_dev(int sk, SkOptsEntry *soe)
      68                 :            : {
      69                 :        108 :         char *n = soe->so_bound_dev;
      70                 :            : 
      71         [ +  + ]:        108 :         if (!n)
      72                 :            :                 return 0;
      73                 :            : 
      74                 :          2 :         pr_debug("\tBinding socket to %s dev\n", n);
      75                 :        108 :         return do_restore_opt(sk, SOL_SOCKET, SO_BINDTODEVICE, n, strlen(n));
      76                 :            : }
      77                 :            : 
      78                 :            : /*
      79                 :            :  * Protobuf handles le/be himself, but the sock_filter is not just u64,
      80                 :            :  * it's a structure and we have to preserve the fields order to be able
      81                 :            :  * to move socket image across architectures.
      82                 :            :  */
      83                 :            : 
      84                 :          2 : static void encode_filter(struct sock_filter *f, uint64_t *img, int n)
      85                 :            : {
      86                 :            :         int i;
      87                 :            : 
      88                 :            :         BUILD_BUG_ON(sizeof(*f) != sizeof(*img));
      89                 :            : 
      90         [ +  + ]:         30 :         for (i = 0; i < n; i++)
      91                 :         84 :                 img[i] = ((uint64_t)f[i].code << 48) |
      92                 :         56 :                          ((uint64_t)f[i].jt << 40) |
      93                 :         56 :                          ((uint64_t)f[i].jf << 32) |
      94                 :         28 :                          ((uint64_t)f[i].k << 0);
      95                 :          2 : }
      96                 :            : 
      97                 :          2 : static void decode_filter(uint64_t *img, struct sock_filter *f, int n)
      98                 :            : {
      99                 :            :         int i;
     100                 :            : 
     101         [ +  + ]:         30 :         for (i = 0; i < n; i++) {
     102                 :         28 :                 f[i].code = img[i] >> 48;
     103                 :         28 :                 f[i].jt = img[i] >> 40;
     104                 :         28 :                 f[i].jf = img[i] >> 32;
     105                 :         28 :                 f[i].k = img[i] >> 0;
     106                 :            :         }
     107                 :          2 : }
     108                 :            : 
     109                 :         99 : static int dump_socket_filter(int sk, SkOptsEntry *soe)
     110                 :            : {
     111                 :         99 :         socklen_t len = 0;
     112                 :            :         int ret;
     113                 :            :         struct sock_filter *flt;
     114                 :            : 
     115                 :         99 :         ret = getsockopt(sk, SOL_SOCKET, SO_GET_FILTER, NULL, &len);
     116 [ #  # ][ -  + ]:         99 :         if (ret && errno != ENOPROTOOPT) {
     117                 :          0 :                 pr_perror("Can't get socket filter len");
     118                 :            :                 return ret;
     119                 :            :         }
     120                 :            : 
     121         [ +  + ]:         99 :         if (!len) {
     122                 :         97 :                 pr_info("No filter for socket\n");
     123                 :            :                 return 0;
     124                 :            :         }
     125                 :            : 
     126         [ -  + ]:          2 :         flt = xmalloc(len * sizeof(*flt));
     127         [ +  - ]:          2 :         if (!flt)
     128                 :            :                 return -1;
     129                 :            : 
     130                 :          2 :         ret = getsockopt(sk, SOL_SOCKET, SO_GET_FILTER, flt, &len);
     131         [ -  + ]:          2 :         if (ret) {
     132                 :          0 :                 pr_perror("Can't get socket filter\n");
     133                 :            :                 return ret;
     134                 :            :         }
     135                 :            : 
     136         [ -  + ]:          2 :         soe->so_filter = xmalloc(len * sizeof(*soe->so_filter));
     137         [ +  - ]:          2 :         if (!soe->so_filter)
     138                 :            :                 return -1;
     139                 :            : 
     140                 :          2 :         encode_filter(flt, soe->so_filter, len);
     141                 :          2 :         soe->n_so_filter = len;
     142         [ +  - ]:         99 :         xfree(flt);
     143                 :            :         return 0;
     144                 :            : }
     145                 :            : 
     146                 :        108 : static int restore_socket_filter(int sk, SkOptsEntry *soe)
     147                 :            : {
     148                 :            :         int ret;
     149                 :            :         struct sock_fprog sfp;
     150                 :            : 
     151         [ +  + ]:        108 :         if (!soe->n_so_filter)
     152                 :            :                 return 0;
     153                 :            : 
     154                 :          2 :         pr_info("Restoring socket filter\n");
     155                 :          2 :         sfp.len = soe->n_so_filter;
     156         [ -  + ]:          2 :         sfp.filter = xmalloc(soe->n_so_filter * sfp.len);
     157         [ +  - ]:          2 :         if (!sfp.filter)
     158                 :            :                 return -1;
     159                 :            : 
     160                 :          2 :         decode_filter(soe->so_filter, sfp.filter, sfp.len);
     161                 :          2 :         ret = restore_opt(sk, SOL_SOCKET, SO_ATTACH_FILTER, &sfp);
     162         [ +  - ]:        108 :         xfree(sfp.filter);
     163                 :            : 
     164                 :            :         return ret;
     165                 :            : }
     166                 :            : 
     167                 :            : static struct socket_desc *sockets[SK_HASH_SIZE];
     168                 :            : 
     169                 :        142 : struct socket_desc *lookup_socket(int ino, int family)
     170                 :            : {
     171                 :            :         struct socket_desc *sd;
     172                 :            : 
     173                 :        142 :         pr_debug("\tSearching for socket %x (family %d)\n", ino, family);
     174         [ +  + ]:        400 :         for (sd = sockets[ino % SK_HASH_SIZE]; sd; sd = sd->next)
     175         [ +  + ]:        258 :                 if (sd->ino == ino) {
     176         [ -  + ]:        134 :                         BUG_ON(sd->family != family);
     177                 :        134 :                         return sd;
     178                 :            :                 }
     179                 :            : 
     180                 :            :         return NULL;
     181                 :            : }
     182                 :            : 
     183                 :       7091 : int sk_collect_one(int ino, int family, struct socket_desc *d)
     184                 :            : {
     185                 :            :         struct socket_desc **chain;
     186                 :            : 
     187                 :       7091 :         d->ino               = ino;
     188                 :       7091 :         d->family    = family;
     189                 :       7091 :         d->already_dumped = 0;
     190                 :            : 
     191                 :       7091 :         chain = &sockets[ino % SK_HASH_SIZE];
     192                 :       7091 :         d->next = *chain;
     193                 :       7091 :         *chain = d;
     194                 :            : 
     195                 :       7091 :         return 0;
     196                 :            : }
     197                 :            : 
     198                 :        974 : int do_restore_opt(int sk, int level, int name, void *val, int len)
     199                 :            : {
     200         [ -  + ]:        974 :         if (setsockopt(sk, level, name, val, len) < 0) {
     201                 :          0 :                 pr_perror("Can't set %d:%d (len %d)", level, name, len);
     202                 :        974 :                 return -1;
     203                 :            :         }
     204                 :            : 
     205                 :            :         return 0;
     206                 :            : }
     207                 :            : 
     208                 :            : /*
     209                 :            :  * Set sizes of buffers to maximum and prevent blocking
     210                 :            :  * Caller of this fn should call other socket restoring
     211                 :            :  * routines to drop the non-blocking and set proper send
     212                 :            :  * and receive buffers.
     213                 :            :  */
     214                 :         53 : int restore_prepare_socket(int sk)
     215                 :            : {
     216                 :            :         int flags;
     217                 :            : 
     218                 :            :         /* In kernel a bufsize has type int and a value is doubled. */
     219                 :         53 :         u32 maxbuf = INT_MAX / 2;
     220                 :            : 
     221         [ +  - ]:         53 :         if (restore_opt(sk, SOL_SOCKET, SO_SNDBUFFORCE, &maxbuf))
     222                 :            :                 return -1;
     223         [ +  - ]:         53 :         if (restore_opt(sk, SOL_SOCKET, SO_RCVBUFFORCE, &maxbuf))
     224                 :            :                 return -1;
     225                 :            : 
     226                 :            :         /* Prevent blocking on restore */
     227                 :         53 :         flags = fcntl(sk, F_GETFL, 0);
     228         [ -  + ]:         53 :         if (flags == -1) {
     229                 :          0 :                 pr_perror("Unable to get flags for %d", sk);
     230                 :            :                 return -1;
     231                 :            :         }
     232         [ -  + ]:         53 :         if (fcntl(sk, F_SETFL, flags | O_NONBLOCK) ) {
     233                 :         53 :                 pr_perror("Unable to set O_NONBLOCK for %d", sk);
     234                 :            :                 return -1;
     235                 :            :         }
     236                 :            : 
     237                 :            :         return 0;
     238                 :            : }
     239                 :            : 
     240                 :        108 : int restore_socket_opts(int sk, SkOptsEntry *soe)
     241                 :            : {
     242                 :        108 :         int ret = 0, val;
     243                 :            :         struct timeval tv;
     244                 :            : 
     245                 :        108 :         pr_info("%d restore sndbuf %d rcv buf %d\n", sk, soe->so_sndbuf, soe->so_rcvbuf);
     246                 :        108 :         ret |= restore_opt(sk, SOL_SOCKET, SO_SNDBUFFORCE, &soe->so_sndbuf);
     247                 :        108 :         ret |= restore_opt(sk, SOL_SOCKET, SO_RCVBUFFORCE, &soe->so_rcvbuf);
     248         [ +  - ]:        108 :         if (soe->has_so_priority) {
     249                 :        108 :                 pr_debug("\trestore priority %d for socket\n", soe->so_priority);
     250                 :        108 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_PRIORITY, &soe->so_priority);
     251                 :            :         }
     252         [ +  - ]:        108 :         if (soe->has_so_rcvlowat) {
     253                 :        108 :                 pr_debug("\trestore rcvlowat %d for socket\n", soe->so_rcvlowat);
     254                 :        108 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_RCVLOWAT, &soe->so_rcvlowat);
     255                 :            :         }
     256         [ +  - ]:        108 :         if (soe->has_so_mark) {
     257                 :        108 :                 pr_debug("\trestore mark %d for socket\n", soe->so_mark);
     258                 :        108 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_MARK, &soe->so_mark);
     259                 :            :         }
     260 [ +  - ][ +  + ]:        108 :         if (soe->has_so_passcred && soe->so_passcred) {
     261                 :          2 :                 val = 1;
     262                 :          2 :                 pr_debug("\tset passcred for socket\n");
     263                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_PASSCRED, &val);
     264                 :            :         }
     265 [ +  - ][ +  + ]:        108 :         if (soe->has_so_passsec && soe->so_passsec) {
     266                 :          2 :                 val = 1;
     267                 :          2 :                 pr_debug("\tset passsec for socket\n");
     268                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_PASSSEC, &val);
     269                 :            :         }
     270 [ +  - ][ +  + ]:        108 :         if (soe->has_so_dontroute && soe->so_dontroute) {
     271                 :          2 :                 val = 1;
     272                 :          2 :                 pr_debug("\tset dontroute for socket\n");
     273                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_DONTROUTE, &val);
     274                 :            :         }
     275 [ +  - ][ +  + ]:        108 :         if (soe->has_so_no_check && soe->so_no_check) {
     276                 :          2 :                 val = 1;
     277                 :          2 :                 pr_debug("\tset no_check for socket\n");
     278                 :          2 :                 ret |= restore_opt(sk, SOL_SOCKET, SO_NO_CHECK, &val);
     279                 :            :         }
     280                 :            : 
     281                 :        108 :         tv.tv_sec = soe->so_snd_tmo_sec;
     282                 :        108 :         tv.tv_usec = soe->so_snd_tmo_usec;
     283                 :        108 :         ret |= restore_opt(sk, SOL_SOCKET, SO_SNDTIMEO, &tv);
     284                 :            : 
     285                 :        108 :         tv.tv_sec = soe->so_rcv_tmo_sec;
     286                 :        108 :         tv.tv_usec = soe->so_rcv_tmo_usec;
     287                 :        108 :         ret |= restore_opt(sk, SOL_SOCKET, SO_RCVTIMEO, &tv);
     288                 :            : 
     289                 :        108 :         ret |= restore_bound_dev(sk, soe);
     290                 :        108 :         ret |= restore_socket_filter(sk, soe);
     291                 :            : 
     292                 :            :         /* The restore of SO_REUSEADDR depends on type of socket */
     293                 :            : 
     294                 :        108 :         return ret;
     295                 :            : }
     296                 :            : 
     297                 :       1332 : int do_dump_opt(int sk, int level, int name, void *val, int len)
     298                 :            : {
     299                 :       1332 :         socklen_t aux = len;
     300                 :            : 
     301         [ -  + ]:       1332 :         if (getsockopt(sk, level, name, val, &aux) < 0) {
     302                 :          0 :                 pr_perror("Can't get %d:%d opt", level, name);
     303                 :            :                 return -1;
     304                 :            :         }
     305                 :            : 
     306         [ -  + ]:       1332 :         if (aux != len) {
     307                 :       1332 :                 pr_err("Len mismatch on %d:%d : %d, want %d\n",
     308                 :            :                                 level, name, aux, len);
     309                 :            :                 return -1;
     310                 :            :         }
     311                 :            : 
     312                 :            :         return 0;
     313                 :            : }
     314                 :            : 
     315                 :         99 : int dump_socket_opts(int sk, SkOptsEntry *soe)
     316                 :            : {
     317                 :         99 :         int ret = 0, val;
     318                 :            :         struct timeval tv;
     319                 :            : 
     320                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_SNDBUF, &soe->so_sndbuf);
     321                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_RCVBUF, &soe->so_rcvbuf);
     322                 :         99 :         soe->has_so_priority = true;
     323                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_PRIORITY, &soe->so_priority);
     324                 :         99 :         soe->has_so_rcvlowat = true;
     325                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_RCVLOWAT, &soe->so_rcvlowat);
     326                 :         99 :         soe->has_so_mark = true;
     327                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_MARK, &soe->so_mark);
     328                 :            : 
     329                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_SNDTIMEO, &tv);
     330                 :         99 :         soe->so_snd_tmo_sec = tv.tv_sec;
     331                 :         99 :         soe->so_snd_tmo_usec = tv.tv_usec;
     332                 :            : 
     333                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_RCVTIMEO, &tv);
     334                 :         99 :         soe->so_rcv_tmo_sec = tv.tv_sec;
     335                 :         99 :         soe->so_rcv_tmo_usec = tv.tv_usec;
     336                 :            : 
     337                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_REUSEADDR, &val);
     338                 :         99 :         soe->reuseaddr = val ? true : false;
     339                 :         99 :         soe->has_reuseaddr = true;
     340                 :            : 
     341                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_PASSCRED, &val);
     342                 :         99 :         soe->has_so_passcred = true;
     343                 :         99 :         soe->so_passcred = val ? true : false;
     344                 :            : 
     345                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_PASSSEC, &val);
     346                 :         99 :         soe->has_so_passsec = true;
     347                 :         99 :         soe->so_passsec = val ? true : false;
     348                 :            : 
     349                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_DONTROUTE, &val);
     350                 :         99 :         soe->has_so_dontroute = true;
     351                 :         99 :         soe->so_dontroute = val ? true : false;
     352                 :            : 
     353                 :         99 :         ret |= dump_opt(sk, SOL_SOCKET, SO_NO_CHECK, &val);
     354                 :         99 :         soe->has_so_no_check = true;
     355                 :         99 :         soe->so_no_check = val ? true : false;
     356                 :            : 
     357                 :         99 :         ret |= dump_bound_dev(sk, soe);
     358                 :         99 :         ret |= dump_socket_filter(sk, soe);
     359                 :            : 
     360                 :         99 :         return ret;
     361                 :            : }
     362                 :            : 
     363                 :         99 : void release_skopts(SkOptsEntry *soe)
     364                 :            : {
     365         [ +  + ]:         99 :         xfree(soe->so_filter);
     366         [ +  + ]:         99 :         xfree(soe->so_bound_dev);
     367                 :         99 : }
     368                 :            : 
     369                 :         99 : int dump_socket(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
     370                 :            : {
     371                 :            :         int family;
     372                 :            : 
     373         [ +  - ]:         99 :         if (dump_opt(lfd, SOL_SOCKET, SO_DOMAIN, &family))
     374                 :            :                 return -1;
     375                 :            : 
     376   [ +  +  +  +  :         99 :         switch (family) {
                      - ]
     377                 :            :         case AF_UNIX:
     378                 :         57 :                 return dump_one_unix(p, lfd, cr_fdset);
     379                 :            :         case AF_INET:
     380                 :         25 :                 return dump_one_inet(p, lfd, cr_fdset);
     381                 :            :         case AF_INET6:
     382                 :         13 :                 return dump_one_inet6(p, lfd, cr_fdset);
     383                 :            :         case AF_PACKET:
     384                 :          4 :                 return dump_one_packet_sk(p, lfd, cr_fdset);
     385                 :            :         default:
     386                 :         99 :                 pr_err("BUG! Unknown socket collected\n");
     387                 :            :                 break;
     388                 :            :         }
     389                 :            : 
     390                 :            :         return -1;
     391                 :            : }
     392                 :            : 
     393                 :       2040 : static int inet_receive_one(struct nlmsghdr *h, void *arg)
     394                 :            : {
     395                 :       2040 :         struct inet_diag_req_v2 *i = arg;
     396                 :            :         int type;
     397                 :            : 
     398      [ +  -  + ]:       2040 :         switch (i->sdiag_protocol) {
     399                 :            :         case IPPROTO_TCP:
     400                 :            :                 type = SOCK_STREAM;
     401                 :            :                 break;
     402                 :            :         case IPPROTO_UDP:
     403                 :            :         case IPPROTO_UDPLITE:
     404                 :       1104 :                 type = SOCK_DGRAM;
     405                 :       1104 :                 break;
     406                 :            :         default:
     407                 :          0 :                 BUG_ON(1);
     408                 :          0 :                 return -1;
     409                 :            :         }
     410                 :            : 
     411                 :       2040 :         return inet_collect_one(h, i->sdiag_family, type, i->sdiag_protocol);
     412                 :            : }
     413                 :            : 
     414                 :        167 : int collect_sockets(int pid)
     415                 :            : {
     416                 :        167 :         int err = 0, tmp;
     417                 :        167 :         int rst = -1;
     418                 :            :         int nl;
     419                 :            :         struct {
     420                 :            :                 struct nlmsghdr hdr;
     421                 :            :                 union {
     422                 :            :                         struct unix_diag_req    u;
     423                 :            :                         struct inet_diag_req_v2 i;
     424                 :            :                         struct packet_diag_req  p;
     425                 :            :                 } r;
     426                 :            :         } req;
     427                 :            : 
     428         [ +  + ]:        167 :         if (opts.namespaces_flags & CLONE_NEWNET) {
     429                 :         76 :                 pr_info("Switching to %d's net for collecting sockets\n", pid);
     430                 :            : 
     431         [ +  - ]:         76 :                 if (switch_ns(pid, CLONE_NEWNET, "net", &rst))
     432                 :            :                         return -1;
     433                 :            :         }
     434                 :            : 
     435                 :        167 :         nl = socket(PF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
     436         [ -  + ]:        167 :         if (nl < 0) {
     437                 :          0 :                 pr_perror("Can't create sock diag socket");
     438                 :          0 :                 err = -1;
     439                 :          0 :                 goto out;
     440                 :            :         }
     441                 :            : 
     442                 :        167 :         memset(&req, 0, sizeof(req));
     443                 :        167 :         req.hdr.nlmsg_len       = sizeof(req);
     444                 :        167 :         req.hdr.nlmsg_type      = SOCK_DIAG_BY_FAMILY;
     445                 :        167 :         req.hdr.nlmsg_flags     = NLM_F_DUMP | NLM_F_REQUEST;
     446                 :        167 :         req.hdr.nlmsg_seq       = CR_NLMSG_SEQ;
     447                 :            : 
     448                 :            :         /* Collect UNIX sockets */
     449                 :        167 :         req.r.u.sdiag_family    = AF_UNIX;
     450                 :        167 :         req.r.u.udiag_states    = -1; /* All */
     451                 :        167 :         req.r.u.udiag_show      = UDIAG_SHOW_NAME | UDIAG_SHOW_VFS |
     452                 :            :                                   UDIAG_SHOW_PEER | UDIAG_SHOW_ICONS |
     453                 :            :                                   UDIAG_SHOW_RQLEN;
     454                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), unix_receive_one, NULL);
     455         [ -  + ]:        167 :         if (tmp)
     456                 :          0 :                 err = tmp;
     457                 :            : 
     458                 :            :         /* Collect IPv4 TCP sockets */
     459                 :        167 :         req.r.i.sdiag_family    = AF_INET;
     460                 :        167 :         req.r.i.sdiag_protocol  = IPPROTO_TCP;
     461                 :        167 :         req.r.i.idiag_ext       = 0;
     462                 :            :         /* Only listening and established sockets supported yet */
     463                 :        167 :         req.r.i.idiag_states    = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
     464                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     465         [ -  + ]:        167 :         if (tmp)
     466                 :          0 :                 err = tmp;
     467                 :            : 
     468                 :            :         /* Collect IPv4 UDP sockets */
     469                 :        167 :         req.r.i.sdiag_family    = AF_INET;
     470                 :        167 :         req.r.i.sdiag_protocol  = IPPROTO_UDP;
     471                 :        167 :         req.r.i.idiag_ext       = 0;
     472                 :        167 :         req.r.i.idiag_states    = -1; /* All */
     473                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     474         [ -  + ]:        167 :         if (tmp)
     475                 :          0 :                 err = tmp;
     476                 :            : 
     477                 :            :         /* Collect IPv4 UDP-lite sockets */
     478                 :        167 :         req.r.i.sdiag_family    = AF_INET;
     479                 :        167 :         req.r.i.sdiag_protocol  = IPPROTO_UDPLITE;
     480                 :        167 :         req.r.i.idiag_ext       = 0;
     481                 :        167 :         req.r.i.idiag_states    = -1; /* All */
     482                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     483         [ -  + ]:        167 :         if (tmp)
     484                 :          0 :                 err = tmp;
     485                 :            : 
     486                 :            :         /* Collect IPv6 TCP sockets */
     487                 :        167 :         req.r.i.sdiag_family    = AF_INET6;
     488                 :        167 :         req.r.i.sdiag_protocol  = IPPROTO_TCP;
     489                 :        167 :         req.r.i.idiag_ext       = 0;
     490                 :            :         /* Only listening sockets supported yet */
     491                 :        167 :         req.r.i.idiag_states    = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
     492                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     493         [ -  + ]:        167 :         if (tmp)
     494                 :          0 :                 err = tmp;
     495                 :            : 
     496                 :            :         /* Collect IPv6 UDP sockets */
     497                 :        167 :         req.r.i.sdiag_family    = AF_INET6;
     498                 :        167 :         req.r.i.sdiag_protocol  = IPPROTO_UDP;
     499                 :        167 :         req.r.i.idiag_ext       = 0;
     500                 :        167 :         req.r.i.idiag_states    = -1; /* All */
     501                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     502         [ -  + ]:        167 :         if (tmp)
     503                 :          0 :                 err = tmp;
     504                 :            : 
     505                 :            :         /* Collect IPv6 UDP-lite sockets */
     506                 :        167 :         req.r.i.sdiag_family    = AF_INET6;
     507                 :        167 :         req.r.i.sdiag_protocol  = IPPROTO_UDPLITE;
     508                 :        167 :         req.r.i.idiag_ext       = 0;
     509                 :        167 :         req.r.i.idiag_states    = -1; /* All */
     510                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
     511         [ -  + ]:        167 :         if (tmp)
     512                 :          0 :                 err = tmp;
     513                 :            : 
     514                 :        167 :         req.r.p.sdiag_family    = AF_PACKET;
     515                 :        167 :         req.r.p.sdiag_protocol  = 0;
     516                 :        167 :         req.r.p.pdiag_show      = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST |
     517                 :            :                                         PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG;
     518                 :        167 :         tmp = do_rtnl_req(nl, &req, sizeof(req), packet_receive_one, NULL);
     519         [ -  + ]:        167 :         if (tmp)
     520                 :          0 :                 err = tmp;
     521                 :            : 
     522                 :        167 :         close(nl);
     523                 :            : out:
     524 [ +  + ][ -  + ]:        167 :         if (rst > 0 && restore_ns(rst, CLONE_NEWNET) < 0)
     525                 :        167 :                 err = -1;
     526                 :            :         return err;
     527                 :            : }
     528                 :            : 
     529                 :          0 : static inline char *unknown(u32 val)
     530                 :            : {
     531                 :            :         static char unk[12];
     532                 :          0 :         snprintf(unk, sizeof(unk), "x%d", val);
     533                 :          0 :         return unk;
     534                 :            : }
     535                 :            : 
     536                 :          0 : char *skfamily2s(u32 f)
     537                 :            : {
     538         [ #  # ]:          0 :         if (f == AF_INET)
     539                 :            :                 return " inet";
     540         [ #  # ]:          0 :         else if (f == AF_INET6)
     541                 :            :                 return "inet6";
     542                 :            :         else
     543                 :          0 :                 return unknown(f);
     544                 :            : }
     545                 :            : 
     546                 :          0 : char *sktype2s(u32 t)
     547                 :            : {
     548         [ #  # ]:          0 :         if (t == SOCK_STREAM)
     549                 :            :                 return "stream";
     550         [ #  # ]:          0 :         else if (t == SOCK_DGRAM)
     551                 :            :                 return " dgram";
     552                 :            :         else
     553                 :          0 :                 return unknown(t);
     554                 :            : }
     555                 :            : 
     556                 :          0 : char *skproto2s(u32 p)
     557                 :            : {
     558         [ #  # ]:          0 :         if (p == IPPROTO_UDP)
     559                 :            :                 return "udp";
     560         [ #  # ]:          0 :         else if (p == IPPROTO_UDPLITE)
     561                 :            :                 return "udpl";
     562         [ #  # ]:          0 :         else if (p == IPPROTO_TCP)
     563                 :            :                 return "tcp";
     564                 :            :         else
     565                 :          0 :                 return unknown(p);
     566                 :            : }
     567                 :            : 
     568                 :          0 : char *skstate2s(u32 state)
     569                 :            : {
     570         [ #  # ]:          0 :         if (state == TCP_ESTABLISHED)
     571                 :            :                 return " estab";
     572         [ #  # ]:          0 :         else if (state == TCP_CLOSE)
     573                 :            :                 return "closed";
     574         [ #  # ]:          0 :         else if (state == TCP_LISTEN)
     575                 :            :                 return "listen";
     576                 :            :         else
     577                 :          0 :                 return unknown(state);
     578                 :        621 : }

Generated by: LCOV version 1.9