]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/nl.c
2e97efcca4a447f5f582a904ea100c8b52064fa9
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_HDRLEN
;
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
);
56 size_t tlen
= NLMSG_ALIGN(nlmsg
->nlmsghdr
->nlmsg_len
) + RTA_ALIGN(rtalen
);
58 if (tlen
> nlmsg
->cap
)
61 rta
= NLMSG_TAIL(nlmsg
->nlmsghdr
);
63 rta
->rta_len
= rtalen
;
65 memcpy(RTA_DATA(rta
), data
, len
);
66 nlmsg
->nlmsghdr
->nlmsg_len
= tlen
;
70 extern int nla_put_buffer(struct nlmsg
*nlmsg
, int attr
,
71 const void *data
, size_t size
)
73 return nla_put(nlmsg
, attr
, data
, size
);
76 extern int nla_put_string(struct nlmsg
*nlmsg
, int attr
, const char *string
)
78 return nla_put(nlmsg
, attr
, string
, strlen(string
) + 1);
81 extern int nla_put_u32(struct nlmsg
*nlmsg
, int attr
, int value
)
83 return nla_put(nlmsg
, attr
, &value
, sizeof(value
));
86 extern int nla_put_u16(struct nlmsg
*nlmsg
, int attr
, unsigned short value
)
88 return nla_put(nlmsg
, attr
, &value
, 2);
91 extern int nla_put_attr(struct nlmsg
*nlmsg
, int attr
)
93 return nla_put(nlmsg
, attr
, NULL
, 0);
96 struct rtattr
*nla_begin_nested(struct nlmsg
*nlmsg
, int attr
)
98 struct rtattr
*rtattr
= NLMSG_TAIL(nlmsg
->nlmsghdr
);
100 if (nla_put_attr(nlmsg
, attr
))
106 void nla_end_nested(struct nlmsg
*nlmsg
, struct rtattr
*attr
)
108 attr
->rta_len
= (void *)NLMSG_TAIL(nlmsg
->nlmsghdr
) - (void *)attr
;
111 extern struct nlmsg
*nlmsg_alloc(size_t size
)
114 size_t len
= NLMSG_HDRLEN
+ NLMSG_ALIGN(size
);
116 nlmsg
= (struct nlmsg
*)malloc(sizeof(struct nlmsg
));
120 nlmsg
->nlmsghdr
= (struct nlmsghdr
*)malloc(len
);
121 if (!nlmsg
->nlmsghdr
)
124 memset(nlmsg
->nlmsghdr
, 0, len
);
126 nlmsg
->nlmsghdr
->nlmsg_len
= NLMSG_HDRLEN
;
134 extern void *nlmsg_reserve(struct nlmsg
*nlmsg
, size_t len
)
137 size_t nlmsg_len
= nlmsg
->nlmsghdr
->nlmsg_len
;
138 size_t tlen
= NLMSG_ALIGN(len
);
140 if (nlmsg_len
+ tlen
> nlmsg
->cap
)
143 buf
= ((char *)(nlmsg
->nlmsghdr
)) + nlmsg_len
;
144 nlmsg
->nlmsghdr
->nlmsg_len
+= tlen
;
147 memset(buf
+ len
, 0, tlen
- len
);
152 extern struct nlmsg
*nlmsg_alloc_reserve(size_t size
)
156 nlmsg
= nlmsg_alloc(size
);
160 /* Just set message length to cap directly. */
161 nlmsg
->nlmsghdr
->nlmsg_len
= nlmsg
->cap
;
165 extern void nlmsg_free(struct nlmsg
*nlmsg
)
170 free(nlmsg
->nlmsghdr
);
174 extern int __netlink_recv(struct nl_handler
*handler
, struct nlmsghdr
*nlmsghdr
)
177 struct sockaddr_nl nladdr
;
179 .iov_base
= nlmsghdr
,
180 .iov_len
= nlmsghdr
->nlmsg_len
,
183 struct msghdr msg
= {
185 .msg_namelen
= sizeof(nladdr
),
190 memset(&nladdr
, 0, sizeof(nladdr
));
191 nladdr
.nl_family
= AF_NETLINK
;
193 nladdr
.nl_groups
= 0;
196 ret
= recvmsg(handler
->fd
, &msg
, 0);
207 if (msg
.msg_flags
& MSG_TRUNC
&& (ret
== nlmsghdr
->nlmsg_len
))
213 extern int netlink_rcv(struct nl_handler
*handler
, struct nlmsg
*answer
)
215 return __netlink_recv(handler
, answer
->nlmsghdr
);
218 extern int __netlink_send(struct nl_handler
*handler
, struct nlmsghdr
*nlmsghdr
)
221 struct sockaddr_nl nladdr
;
223 .iov_base
= nlmsghdr
,
224 .iov_len
= nlmsghdr
->nlmsg_len
,
226 struct msghdr msg
= {
228 .msg_namelen
= sizeof(nladdr
),
233 memset(&nladdr
, 0, sizeof(nladdr
));
234 nladdr
.nl_family
= AF_NETLINK
;
236 nladdr
.nl_groups
= 0;
238 ret
= sendmsg(handler
->fd
, &msg
, MSG_NOSIGNAL
);
245 extern int netlink_send(struct nl_handler
*handler
, struct nlmsg
*nlmsg
)
247 return __netlink_send(handler
, nlmsg
->nlmsghdr
);
250 extern int __netlink_transaction(struct nl_handler
*handler
,
251 struct nlmsghdr
*request
,
252 struct nlmsghdr
*answer
)
256 ret
= __netlink_send(handler
, request
);
260 ret
= __netlink_recv(handler
, answer
);
264 if (answer
->nlmsg_type
== NLMSG_ERROR
) {
265 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(answer
);
272 extern int netlink_transaction(struct nl_handler
*handler
,
273 struct nlmsg
*request
, struct nlmsg
*answer
)
275 return __netlink_transaction(handler
, request
->nlmsghdr
,
279 extern int netlink_open(struct nl_handler
*handler
, int protocol
)
286 memset(handler
, 0, sizeof(*handler
));
288 handler
->fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
292 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_SNDBUF
,
293 &sndbuf
, sizeof(sndbuf
)) < 0)
296 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_RCVBUF
,
297 &rcvbuf
,sizeof(rcvbuf
)) < 0)
300 memset(&handler
->local
, 0, sizeof(handler
->local
));
301 handler
->local
.nl_family
= AF_NETLINK
;
302 handler
->local
.nl_groups
= 0;
304 if (bind(handler
->fd
, (struct sockaddr
*)&handler
->local
,
305 sizeof(handler
->local
)) < 0)
308 socklen
= sizeof(handler
->local
);
309 if (getsockname(handler
->fd
, (struct sockaddr
*)&handler
->local
,
313 if (socklen
!= sizeof(handler
->local
)) {
318 if (handler
->local
.nl_family
!= AF_NETLINK
) {
323 handler
->seq
= time(NULL
);
333 extern int netlink_close(struct nl_handler
*handler
)