]>
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
28 #include <linux/netlink.h>
29 #include <linux/rtnetlink.h>
33 #include <sys/socket.h>
41 lxc_log_define(nl
, lxc
);
43 extern size_t nlmsg_len(const struct nlmsg
*nlmsg
)
45 return nlmsg
->nlmsghdr
->nlmsg_len
- NLMSG_HDRLEN
;
48 extern void *nlmsg_data(struct nlmsg
*nlmsg
)
50 char *data
= ((char *)nlmsg
) + NLMSG_HDRLEN
;
51 if (!nlmsg_len(nlmsg
))
56 static int nla_put(struct nlmsg
*nlmsg
, int attr
,
57 const void *data
, size_t len
)
60 size_t rtalen
= RTA_LENGTH(len
);
61 size_t tlen
= NLMSG_ALIGN(nlmsg
->nlmsghdr
->nlmsg_len
) + RTA_ALIGN(rtalen
);
63 if (tlen
> nlmsg
->cap
)
66 rta
= NLMSG_TAIL(nlmsg
->nlmsghdr
);
68 rta
->rta_len
= rtalen
;
70 memcpy(RTA_DATA(rta
), data
, len
);
71 nlmsg
->nlmsghdr
->nlmsg_len
= tlen
;
75 extern int nla_put_buffer(struct nlmsg
*nlmsg
, int attr
,
76 const void *data
, size_t size
)
78 return nla_put(nlmsg
, attr
, data
, size
);
81 extern int nla_put_string(struct nlmsg
*nlmsg
, int attr
, const char *string
)
83 return nla_put(nlmsg
, attr
, string
, strlen(string
) + 1);
86 extern int nla_put_u32(struct nlmsg
*nlmsg
, int attr
, int value
)
88 return nla_put(nlmsg
, attr
, &value
, sizeof(value
));
91 extern int nla_put_u16(struct nlmsg
*nlmsg
, int attr
, unsigned short value
)
93 return nla_put(nlmsg
, attr
, &value
, 2);
96 extern int nla_put_attr(struct nlmsg
*nlmsg
, int attr
)
98 return nla_put(nlmsg
, attr
, NULL
, 0);
101 struct rtattr
*nla_begin_nested(struct nlmsg
*nlmsg
, int attr
)
103 struct rtattr
*rtattr
= NLMSG_TAIL(nlmsg
->nlmsghdr
);
105 if (nla_put_attr(nlmsg
, attr
))
111 void nla_end_nested(struct nlmsg
*nlmsg
, struct rtattr
*attr
)
113 attr
->rta_len
= (void *)NLMSG_TAIL(nlmsg
->nlmsghdr
) - (void *)attr
;
116 extern struct nlmsg
*nlmsg_alloc(size_t size
)
119 size_t len
= NLMSG_HDRLEN
+ NLMSG_ALIGN(size
);
121 nlmsg
= (struct nlmsg
*)malloc(sizeof(struct nlmsg
));
125 nlmsg
->nlmsghdr
= (struct nlmsghdr
*)malloc(len
);
126 if (!nlmsg
->nlmsghdr
)
129 memset(nlmsg
->nlmsghdr
, 0, len
);
131 nlmsg
->nlmsghdr
->nlmsg_len
= NLMSG_HDRLEN
;
139 extern void *nlmsg_reserve(struct nlmsg
*nlmsg
, size_t len
)
142 size_t nlmsg_len
= nlmsg
->nlmsghdr
->nlmsg_len
;
143 size_t tlen
= NLMSG_ALIGN(len
);
145 if (nlmsg_len
+ tlen
> nlmsg
->cap
)
148 buf
= ((char *)(nlmsg
->nlmsghdr
)) + nlmsg_len
;
149 nlmsg
->nlmsghdr
->nlmsg_len
+= tlen
;
152 memset(buf
+ len
, 0, tlen
- len
);
157 extern struct nlmsg
*nlmsg_alloc_reserve(size_t size
)
161 nlmsg
= nlmsg_alloc(size
);
165 /* Just set message length to cap directly. */
166 nlmsg
->nlmsghdr
->nlmsg_len
= nlmsg
->cap
;
170 extern void nlmsg_free(struct nlmsg
*nlmsg
)
175 free(nlmsg
->nlmsghdr
);
179 extern int __netlink_recv(struct nl_handler
*handler
, struct nlmsghdr
*nlmsghdr
)
182 struct sockaddr_nl nladdr
;
184 .iov_base
= nlmsghdr
,
185 .iov_len
= nlmsghdr
->nlmsg_len
,
188 struct msghdr msg
= {
190 .msg_namelen
= sizeof(nladdr
),
195 memset(&nladdr
, 0, sizeof(nladdr
));
196 nladdr
.nl_family
= AF_NETLINK
;
198 nladdr
.nl_groups
= 0;
201 ret
= recvmsg(handler
->fd
, &msg
, 0);
212 if (msg
.msg_flags
& MSG_TRUNC
&& (ret
== nlmsghdr
->nlmsg_len
)) {
220 extern int netlink_rcv(struct nl_handler
*handler
, struct nlmsg
*answer
)
222 return __netlink_recv(handler
, answer
->nlmsghdr
);
225 extern int __netlink_send(struct nl_handler
*handler
, struct nlmsghdr
*nlmsghdr
)
228 struct sockaddr_nl nladdr
;
230 .iov_base
= nlmsghdr
,
231 .iov_len
= nlmsghdr
->nlmsg_len
,
233 struct msghdr msg
= {
235 .msg_namelen
= sizeof(nladdr
),
240 memset(&nladdr
, 0, sizeof(nladdr
));
241 nladdr
.nl_family
= AF_NETLINK
;
243 nladdr
.nl_groups
= 0;
245 ret
= sendmsg(handler
->fd
, &msg
, MSG_NOSIGNAL
);
252 extern int netlink_send(struct nl_handler
*handler
, struct nlmsg
*nlmsg
)
254 return __netlink_send(handler
, nlmsg
->nlmsghdr
);
257 extern int __netlink_transaction(struct nl_handler
*handler
,
258 struct nlmsghdr
*request
,
259 struct nlmsghdr
*answer
)
263 ret
= __netlink_send(handler
, request
);
267 ret
= __netlink_recv(handler
, answer
);
272 if (answer
->nlmsg_type
== NLMSG_ERROR
) {
273 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(answer
);
282 extern int netlink_transaction(struct nl_handler
*handler
,
283 struct nlmsg
*request
, struct nlmsg
*answer
)
285 return __netlink_transaction(handler
, request
->nlmsghdr
,
289 extern int netlink_open(struct nl_handler
*handler
, int protocol
)
296 memset(handler
, 0, sizeof(*handler
));
298 handler
->fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
302 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_SNDBUF
,
303 &sndbuf
, sizeof(sndbuf
)) < 0)
306 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_RCVBUF
,
307 &rcvbuf
,sizeof(rcvbuf
)) < 0)
310 memset(&handler
->local
, 0, sizeof(handler
->local
));
311 handler
->local
.nl_family
= AF_NETLINK
;
312 handler
->local
.nl_groups
= 0;
314 if (bind(handler
->fd
, (struct sockaddr
*)&handler
->local
,
315 sizeof(handler
->local
)) < 0)
318 socklen
= sizeof(handler
->local
);
319 if (getsockname(handler
->fd
, (struct sockaddr
*)&handler
->local
,
323 if (socklen
!= sizeof(handler
->local
)) {
328 if (handler
->local
.nl_family
!= AF_NETLINK
) {
333 handler
->seq
= time(NULL
);
343 extern int netlink_close(struct nl_handler
*handler
)
350 int addattr(struct nlmsghdr
*n
, size_t maxlen
, int type
, const void *data
,
353 int len
= RTA_LENGTH(alen
);
357 if (NLMSG_ALIGN(n
->nlmsg_len
) + RTA_ALIGN(len
) > maxlen
)
361 rta
->rta_type
= type
;
364 memcpy(RTA_DATA(rta
), data
, alen
);
365 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + RTA_ALIGN(len
);