Coverage Report

Created: 2025-07-11 06:39

/src/numactl/rtnetlink.c
Line
Count
Source (jump to first uncovered line)
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
2
{
13
2
  struct rtattr *rta = (void *)m + NLMSG_ALIGN(m->nlmsg_len);
14
2
  int rtalen = RTA_LENGTH(len);
15
16
2
  rta->rta_type = type;
17
2
  rta->rta_len = rtalen;
18
2
  m->nlmsg_len = NLMSG_ALIGN(m->nlmsg_len) + RTA_ALIGN(rtalen);
19
2
  return RTA_DATA(rta);
20
2
}
21
22
hidden struct rtattr *rta_get(struct nlmsghdr *m, struct rtattr *p, int offset)
23
6
{
24
6
  struct rtattr *rta;
25
26
6
  if (p) {
27
4
    rta = RTA_NEXT(p, m->nlmsg_len);
28
4
    if (!RTA_OK(rta, m->nlmsg_len))
29
0
      return NULL;
30
4
  } else {
31
2
    rta = (void *)m + NLMSG_ALIGN(offset);
32
2
  }
33
6
  return rta;
34
6
}
35
36
hidden int
37
rta_put_address(struct nlmsghdr *msg, int type, struct sockaddr *adr)
38
2
{
39
2
  switch (adr->sa_family) {
40
2
  case AF_INET: {
41
2
    struct in_addr *i = rta_put(msg, type, 4);
42
2
    *i = ((struct sockaddr_in *)adr)->sin_addr;
43
2
    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
2
  }
53
2
  return 0;
54
2
}
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
2
{
60
2
  int rsk;
61
2
  int n;
62
2
  int e;
63
64
  /* Use a private socket to avoid having to keep state
65
     for a sequence number. */
66
2
  rsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
67
2
  if (rsk < 0)
68
0
    return -1;
69
2
  n = sendto(rsk, msg, msg->nlmsg_len, 0, (struct sockaddr *)adr,
70
2
       sizeof(struct sockaddr_nl));
71
2
  if (n >= 0) {
72
2
    socklen_t adrlen = sizeof(struct sockaddr_nl);
73
2
    n = recvfrom(rsk, msg, buflen, 0, (struct sockaddr *)adr,
74
2
           &adrlen);
75
2
  }
76
2
  e = errno;
77
2
  close(rsk);
78
2
  errno = e;
79
2
  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
2
  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
2
  return 0;
89
2
}