~ubuntu-branches/ubuntu/precise/numactl/precise

« back to all changes in this revision

Viewing changes to rtnetlink.c

  • Committer: Package Import Robot
  • Author(s): Ian Wienand
  • Date: 2012-02-03 09:50:36 UTC
  • mfrom: (1.3.7)
  • Revision ID: package-import@ubuntu.com-20120203095036-y9vbkhcu1ho3z8hm
Tags: 2.0.8~rc3-1
New upstream

Show diffs side-by-side

added added

removed removed

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