]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/nl.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <sys/socket.h>
30 #include <linux/netlink.h>
31 #include <linux/rtnetlink.h>
35 #define NLMSG_TAIL(nmsg) \
36 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
38 extern size_t nlmsg_len(const struct nlmsg
*nlmsg
)
40 return nlmsg
->nlmsghdr
.nlmsg_len
- NLMSG_HDRLEN
;
43 extern void *nlmsg_data(struct nlmsg
*nlmsg
)
45 char *data
= ((char *)nlmsg
) + NLMSG_ALIGN(sizeof(struct nlmsghdr
));
46 if (!nlmsg_len(nlmsg
))
51 static int nla_put(struct nlmsg
*nlmsg
, int attr
,
52 const void *data
, size_t len
)
55 size_t rtalen
= RTA_LENGTH(len
);
57 rta
= NLMSG_TAIL(&nlmsg
->nlmsghdr
);
59 rta
->rta_len
= rtalen
;
60 memcpy(RTA_DATA(rta
), data
, len
);
61 nlmsg
->nlmsghdr
.nlmsg_len
=
62 NLMSG_ALIGN(nlmsg
->nlmsghdr
.nlmsg_len
) + RTA_ALIGN(rtalen
);
66 extern int nla_put_buffer(struct nlmsg
*nlmsg
, int attr
,
67 const void *data
, size_t size
)
69 return nla_put(nlmsg
, attr
, data
, size
);
72 extern int nla_put_string(struct nlmsg
*nlmsg
, int attr
, const char *string
)
74 return nla_put(nlmsg
, attr
, string
, strlen(string
) + 1);
77 extern int nla_put_u32(struct nlmsg
*nlmsg
, int attr
, int value
)
79 return nla_put(nlmsg
, attr
, &value
, sizeof(value
));
82 extern int nla_put_u16(struct nlmsg
*nlmsg
, int attr
, unsigned short value
)
84 return nla_put(nlmsg
, attr
, &value
, 2);
87 extern int nla_put_attr(struct nlmsg
*nlmsg
, int attr
)
89 return nla_put(nlmsg
, attr
, NULL
, 0);
92 struct rtattr
*nla_begin_nested(struct nlmsg
*nlmsg
, int attr
)
94 struct rtattr
*rtattr
= NLMSG_TAIL(&nlmsg
->nlmsghdr
);
96 if (nla_put_attr(nlmsg
, attr
))
102 void nla_end_nested(struct nlmsg
*nlmsg
, struct rtattr
*attr
)
104 attr
->rta_len
= (void *)NLMSG_TAIL(&nlmsg
->nlmsghdr
) - (void *)attr
;
107 extern struct nlmsg
*nlmsg_alloc(size_t size
)
110 size_t len
= NLMSG_ALIGN(size
) + NLMSG_ALIGN(sizeof(struct nlmsghdr
*));
112 nlmsg
= (struct nlmsg
*)malloc(len
);
116 memset(nlmsg
, 0, len
);
117 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_ALIGN(size
);
122 extern void nlmsg_free(struct nlmsg
*nlmsg
)
127 extern int netlink_rcv(struct nl_handler
*handler
, struct nlmsg
*answer
)
130 struct sockaddr_nl nladdr
;
133 .iov_len
= answer
->nlmsghdr
.nlmsg_len
,
136 struct msghdr msg
= {
138 .msg_namelen
= sizeof(nladdr
),
143 memset(&nladdr
, 0, sizeof(nladdr
));
144 nladdr
.nl_family
= AF_NETLINK
;
146 nladdr
.nl_groups
= 0;
149 ret
= recvmsg(handler
->fd
, &msg
, 0);
159 if (msg
.msg_flags
& MSG_TRUNC
&&
160 ret
== answer
->nlmsghdr
.nlmsg_len
)
166 extern int netlink_send(struct nl_handler
*handler
, struct nlmsg
*nlmsg
)
168 struct sockaddr_nl nladdr
;
170 .iov_base
= (void*)nlmsg
,
171 .iov_len
= nlmsg
->nlmsghdr
.nlmsg_len
,
173 struct msghdr msg
= {
175 .msg_namelen
= sizeof(nladdr
),
181 memset(&nladdr
, 0, sizeof(nladdr
));
182 nladdr
.nl_family
= AF_NETLINK
;
184 nladdr
.nl_groups
= 0;
186 ret
= sendmsg(handler
->fd
, &msg
, 0);
194 #define NLMSG_ERROR 0x2
196 extern int netlink_transaction(struct nl_handler
*handler
,
197 struct nlmsg
*request
, struct nlmsg
*answer
)
201 ret
= netlink_send(handler
, request
);
205 ret
= netlink_rcv(handler
, answer
);
209 if (answer
->nlmsghdr
.nlmsg_type
== NLMSG_ERROR
) {
210 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(answer
);
217 extern int netlink_open(struct nl_handler
*handler
, int protocol
)
223 memset(handler
, 0, sizeof(*handler
));
225 handler
->fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
229 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_SNDBUF
,
230 &sndbuf
, sizeof(sndbuf
)) < 0)
233 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_RCVBUF
,
234 &rcvbuf
,sizeof(rcvbuf
)) < 0)
237 memset(&handler
->local
, 0, sizeof(handler
->local
));
238 handler
->local
.nl_family
= AF_NETLINK
;
239 handler
->local
.nl_groups
= 0;
241 if (bind(handler
->fd
, (struct sockaddr
*)&handler
->local
,
242 sizeof(handler
->local
)) < 0)
245 socklen
= sizeof(handler
->local
);
246 if (getsockname(handler
->fd
, (struct sockaddr
*)&handler
->local
,
250 if (socklen
!= sizeof(handler
->local
))
253 if (handler
->local
.nl_family
!= AF_NETLINK
)
256 handler
->seq
= time(NULL
);
261 extern int netlink_close(struct nl_handler
*handler
)