Coverage Report

Created: 2026-01-10 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/numactl/rtnetlink.c
Line
Count
Source
1
/* Simple LPGLed rtnetlink library */
2
#include <sys/socket.h>
3
#include <linux/rtnetlink.h>
4
#include <linux/netlink.h>
5
#include <netinet/in.h>
6
#include <errno.h>
7
#include <unistd.h>
8
#define hidden __attribute__((visibility("hidden")))
9
#include "rtnetlink.h"
10
11
hidden void *rta_put(struct nlmsghdr *m, int type, int len)
12
0
{
13
0
  struct rtattr *rta = (void *)m + NLMSG_ALIGN(m->nlmsg_len);
14
0
  int rtalen = RTA_LENGTH(len);
15
16
0
  rta->rta_type = type;
17
0
  rta->rta_len = rtalen;
18
0
  m->nlmsg_len = NLMSG_ALIGN(m->nlmsg_len) + RTA_ALIGN(rtalen);
19
0
  return RTA_DATA(rta);
20
0
}
21
22
hidden struct rtattr *rta_get(struct nlmsghdr *m, struct rtattr *p, int offset)
23
0
{
24
0
  struct rtattr *rta;
25
26
0
  if (p) {
27
0
    rta = RTA_NEXT(p, m->nlmsg_len);
28
0
    if (!RTA_OK(rta, m->nlmsg_len))
29
0
      return NULL;
30
0
  } else {
31
0
    rta = (void *)m + NLMSG_ALIGN(offset);
32
0
  }
33
0
  return rta;
34
0
}
35
36
hidden int
37
rta_put_address(struct nlmsghdr *msg, int type, struct sockaddr *adr)
38
0
{
39
0
  switch (adr->sa_family) {
40
0
  case AF_INET: {
41
0
    struct in_addr *i = rta_put(msg, type, 4);
42
0
    *i = ((struct sockaddr_in *)adr)->sin_addr;
43
0
    break;
44
0
  }
45
0
  case AF_INET6: {
46
0
    struct in6_addr *i6 = rta_put(msg, type, 16);
47
0
    *i6 = ((struct sockaddr_in6 *)adr)->sin6_addr;
48
0
    break;
49
0
  }
50
0
  default:
51
0
    return -1;
52
0
  }
53
0
  return 0;
54
0
}
55
56
/* Assumes no truncation. Make the buffer large enough. */
57
hidden int
58
rtnetlink_request(struct nlmsghdr *msg, int buflen, struct sockaddr_nl *adr)
59
0
{
60
0
  int rsk;
61
0
  int n;
62
0
  int e;
63
64
  /* Use a private socket to avoid having to keep state
65
     for a sequence number. */
66
0
  rsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
67
0
  if (rsk < 0)
68
0
    return -1;
69
0
  n = sendto(rsk, msg, msg->nlmsg_len, 0, (struct sockaddr *)adr,
70
0
       sizeof(struct sockaddr_nl));
71
0
  if (n >= 0) {
72
0
    socklen_t adrlen = sizeof(struct sockaddr_nl);
73
0
    n = recvfrom(rsk, msg, buflen, 0, (struct sockaddr *)adr,
74
0
           &adrlen);
75
0
  }
76
0
  e = errno;
77
0
  close(rsk);
78
0
  errno = e;
79
0
  if (n < 0)
80
0
    return -1;
81
  /* Assume we only get a single reply back. This is (hopefully?)
82
     safe because it's a single use socket. */
83
0
  if (msg->nlmsg_type == NLMSG_ERROR) {
84
0
    struct nlmsgerr *err = NLMSG_DATA(msg);
85
0
    errno = -err->error;
86
0
    return -1;
87
0
  }
88
0
  return 0;
89
0
}