LCOV - code coverage report
Current view: top level - home/snorch/criu - libnetlink.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 47 66 71.2 %
Date: 2014-04-22 Functions: 4 4 100.0 %
Branches: 27 46 58.7 %

           Branch data     Line data    Source code
       1                 :            : #include <linux/types.h>
       2                 :            : #include <sys/socket.h>
       3                 :            : #include <linux/netlink.h>
       4                 :            : #include <linux/rtnetlink.h>
       5                 :            : #include <string.h>
       6                 :            : #include <unistd.h>
       7                 :            : 
       8                 :            : #include "libnetlink.h"
       9                 :            : #include "util.h"
      10                 :            : 
      11                 :     173364 : int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
      12                 :            : {
      13                 :     173364 :         memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
      14 [ +  + ][ +  - ]:     686288 :         while (RTA_OK(rta, len)) {
                 [ +  - ]
      15 [ +  - ][ +  - ]:     512924 :                 if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
      16                 :     512924 :                         tb[rta->rta_type] = rta;
      17                 :     512924 :                 rta = RTA_NEXT(rta, len);
      18                 :            :         }
      19         [ -  + ]:     173364 :         if (len)
      20                 :          0 :                 pr_warn("Trimmed RTA: len %d, rta_len %d\n", len, rta->rta_len);
      21                 :     173364 :         return 0;
      22                 :            : }
      23                 :            : 
      24                 :       9259 : static int nlmsg_receive(char *buf, int len, int (*cb)(struct nlmsghdr *, void *), void *arg)
      25                 :            : {
      26                 :            :         struct nlmsghdr *hdr;
      27                 :            : 
      28 [ +  + ][ +  - ]:     182623 :         for (hdr = (struct nlmsghdr *)buf; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
                 [ +  - ]
      29         [ -  + ]:     177842 :                 if (hdr->nlmsg_seq != CR_NLMSG_SEQ)
      30                 :          0 :                         continue;
      31         [ +  + ]:     177842 :                 if (hdr->nlmsg_type == NLMSG_DONE) {
      32                 :            :                         int *len = (int *)NLMSG_DATA(hdr);
      33                 :            : 
      34         [ -  + ]:       4264 :                         if (*len < 0) {
      35                 :          0 :                                 pr_err("ERROR %d reported by netlink (%s)\n",
      36                 :            :                                         *len, strerror(-*len));
      37                 :          0 :                                 return *len;
      38                 :            :                         }
      39                 :            : 
      40                 :            :                         return 0;
      41                 :            :                 }
      42         [ +  + ]:     173578 :                 if (hdr->nlmsg_type == NLMSG_ERROR) {
      43                 :            :                         struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr);
      44                 :            : 
      45         [ -  + ]:        214 :                         if (hdr->nlmsg_len - sizeof(*hdr) < sizeof(struct nlmsgerr)) {
      46                 :          0 :                                 pr_err("ERROR truncated\n");
      47                 :          0 :                                 return -1;
      48                 :            :                         }
      49                 :            : 
      50         [ -  + ]:        214 :                         if (err->error == 0)
      51                 :            :                                 return 0;
      52                 :            : 
      53                 :          0 :                         pr_warn("ERROR %d reported by netlink\n", err->error);
      54                 :          0 :                         return err->error;
      55                 :            :                 }
      56         [ +  - ]:     173364 :                 if (cb(hdr, arg))
      57                 :            :                         return -1;
      58                 :            :         }
      59                 :            : 
      60                 :            :         return 1;
      61                 :            : }
      62                 :            : 
      63                 :       4478 : int do_rtnl_req(int nl, void *req, int size,
      64                 :            :                 int (*receive_callback)(struct nlmsghdr *h, void *), void *arg)
      65                 :            : {
      66                 :            :         struct msghdr msg;
      67                 :            :         struct sockaddr_nl nladdr;
      68                 :            :         struct iovec iov;
      69                 :            :         static char buf[4096];
      70                 :            :         int err;
      71                 :            : 
      72                 :            :         memset(&msg, 0, sizeof(msg));
      73                 :       4478 :         msg.msg_name    = &nladdr;
      74                 :       4478 :         msg.msg_namelen = sizeof(nladdr);
      75                 :       4478 :         msg.msg_iov     = &iov;
      76                 :       4478 :         msg.msg_iovlen  = 1;
      77                 :            : 
      78                 :            :         memset(&nladdr, 0, sizeof(nladdr));
      79                 :       4478 :         nladdr.nl_family = AF_NETLINK;
      80                 :            : 
      81                 :       4478 :         iov.iov_base    = req;
      82                 :       4478 :         iov.iov_len     = size;
      83                 :            : 
      84         [ -  + ]:       4478 :         if (sendmsg(nl, &msg, 0) < 0) {
      85                 :          0 :                 err = -errno;
      86                 :          0 :                 pr_perror("Can't send request message");
      87                 :          0 :                 goto err;
      88                 :            :         }
      89                 :            : 
      90                 :       4478 :         iov.iov_base    = buf;
      91                 :       9259 :         iov.iov_len     = sizeof(buf);
      92                 :            : 
      93                 :            :         while (1) {
      94                 :            : 
      95                 :            :                 memset(&msg, 0, sizeof(msg));
      96                 :       9259 :                 msg.msg_name    = &nladdr;
      97                 :       9259 :                 msg.msg_namelen = sizeof(nladdr);
      98                 :       9259 :                 msg.msg_iov     = &iov;
      99                 :       9259 :                 msg.msg_iovlen  = 1;
     100                 :            : 
     101                 :       9259 :                 err = recvmsg(nl, &msg, 0);
     102         [ -  + ]:       9259 :                 if (err < 0) {
     103         [ #  # ]:          0 :                         if (errno == EINTR)
     104                 :          0 :                                 continue;
     105                 :            :                         else {
     106                 :          0 :                                 err = -errno;
     107                 :          0 :                                 pr_perror("Error receiving nl report");
     108                 :          0 :                                 goto err;
     109                 :            :                         }
     110                 :            :                 }
     111         [ +  - ]:       9259 :                 if (err == 0)
     112                 :            :                         break;
     113                 :            : 
     114                 :       9259 :                 err = nlmsg_receive(buf, err, receive_callback, arg);
     115         [ +  - ]:       9259 :                 if (err < 0)
     116                 :            :                         goto err;
     117         [ +  + ]:       9259 :                 if (err == 0)
     118                 :            :                         break;
     119                 :            :         }
     120                 :            : 
     121                 :            :         return 0;
     122                 :            : 
     123                 :            : err:
     124                 :          0 :         return err;
     125                 :            : }
     126                 :            : 
     127                 :        428 : int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
     128                 :            :                 int alen)
     129                 :            : {
     130                 :        428 :         int len = RTA_LENGTH(alen);
     131                 :            :         struct rtattr *rta;
     132                 :            : 
     133         [ -  + ]:        428 :         if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
     134                 :          0 :                 pr_err("addattr_l ERROR: message exceeded bound of %d\n", maxlen);
     135                 :          0 :                 return -1;
     136                 :            :         }
     137                 :            : 
     138                 :        428 :         rta = NLMSG_TAIL(n);
     139                 :        428 :         rta->rta_type = type;
     140                 :        428 :         rta->rta_len = len;
     141                 :        428 :         memcpy(RTA_DATA(rta), data, alen);
     142                 :        428 :         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
     143                 :        428 :         return 0;
     144                 :            : }

Generated by: LCOV version 1.9