]>
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 <dlezcano at fr.ibm.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <sys/socket.h>
30 #include <linux/netlink.h>
31 #include <linux/rtnetlink.h>
34 #define NLMSG_TAIL(nmsg) \
35 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
37 extern size_t nlmsg_len(const struct nlmsg
*nlmsg
)
39 return nlmsg
->nlmsghdr
.nlmsg_len
- NLMSG_HDRLEN
;
42 extern void *nlmsg_data(struct nlmsg
*nlmsg
)
44 char *data
= ((char *)nlmsg
) + NLMSG_ALIGN(sizeof(struct nlmsghdr
));
45 if (!nlmsg_len(nlmsg
))
50 static int nla_put(struct nlmsg
*nlmsg
, int attr
,
51 const void *data
, size_t len
)
54 size_t rtalen
= RTA_LENGTH(len
);
56 rta
= NLMSG_TAIL(&nlmsg
->nlmsghdr
);
58 rta
->rta_len
= rtalen
;
59 memcpy(RTA_DATA(rta
), data
, len
);
60 nlmsg
->nlmsghdr
.nlmsg_len
=
61 NLMSG_ALIGN(nlmsg
->nlmsghdr
.nlmsg_len
) + RTA_ALIGN(rtalen
);
65 extern int nla_put_buffer(struct nlmsg
*nlmsg
, int attr
,
66 const void *data
, size_t size
)
68 return nla_put(nlmsg
, attr
, data
, size
);
71 extern int nla_put_string(struct nlmsg
*nlmsg
, int attr
, const char *string
)
73 return nla_put(nlmsg
, attr
, string
, strlen(string
) + 1);
76 extern int nla_put_u32(struct nlmsg
*nlmsg
, int attr
, int value
)
78 return nla_put(nlmsg
, attr
, &value
, sizeof(value
));
81 extern int nla_put_u16(struct nlmsg
*nlmsg
, int attr
, ushort value
)
83 return nla_put(nlmsg
, attr
, &value
, 2);
86 extern int nla_put_attr(struct nlmsg
*nlmsg
, int attr
)
88 return nla_put(nlmsg
, attr
, NULL
, 0);
91 struct rtattr
*nla_begin_nested(struct nlmsg
*nlmsg
, int attr
)
93 struct rtattr
*rtattr
= NLMSG_TAIL(&nlmsg
->nlmsghdr
);
95 if (nla_put_attr(nlmsg
, attr
))
101 void nla_end_nested(struct nlmsg
*nlmsg
, struct rtattr
*attr
)
103 attr
->rta_len
= (void *)NLMSG_TAIL(&nlmsg
->nlmsghdr
) - (void *)attr
;
106 extern struct nlmsg
*nlmsg_alloc(size_t size
)
109 size_t len
= NLMSG_ALIGN(size
) + NLMSG_ALIGN(sizeof(struct nlmsghdr
*));
111 nlmsg
= (struct nlmsg
*)malloc(len
);
115 memset(nlmsg
, 0, len
);
116 nlmsg
->nlmsghdr
.nlmsg_len
= NLMSG_ALIGN(size
);
121 extern void nlmsg_free(struct nlmsg
*nlmsg
)
126 extern int netlink_rcv(struct nl_handler
*handler
, struct nlmsg
*answer
)
129 struct sockaddr_nl nladdr
;
132 .iov_len
= answer
->nlmsghdr
.nlmsg_len
,
135 struct msghdr msg
= {
137 .msg_namelen
= sizeof(nladdr
),
142 memset(&nladdr
, 0, sizeof(nladdr
));
143 nladdr
.nl_family
= AF_NETLINK
;
145 nladdr
.nl_groups
= 0;
148 ret
= recvmsg(handler
->fd
, &msg
, 0);
158 if (msg
.msg_flags
& MSG_TRUNC
)
164 extern int netlink_send(struct nl_handler
*handler
, struct nlmsg
*nlmsg
)
166 struct sockaddr_nl nladdr
;
168 .iov_base
= (void*)nlmsg
,
169 .iov_len
= nlmsg
->nlmsghdr
.nlmsg_len
,
171 struct msghdr msg
= {
173 .msg_namelen
= sizeof(nladdr
),
179 memset(&nladdr
, 0, sizeof(nladdr
));
180 nladdr
.nl_family
= AF_NETLINK
;
182 nladdr
.nl_groups
= 0;
184 ret
= sendmsg(handler
->fd
, &msg
, 0);
193 #define NLMSG_ERROR 0x2
195 extern int netlink_transaction(struct nl_handler
*handler
,
196 struct nlmsg
*request
, struct nlmsg
*answer
)
200 ret
= netlink_send(handler
, request
);
204 ret
= netlink_rcv(handler
, answer
);
208 if (answer
->nlmsghdr
.nlmsg_type
== NLMSG_ERROR
) {
209 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(answer
);
216 extern int netlink_open(struct nl_handler
*handler
, int protocol
)
222 memset(handler
, 0, sizeof(*handler
));
224 handler
->fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
228 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_SNDBUF
,
229 &sndbuf
, sizeof(sndbuf
)) < 0)
232 if (setsockopt(handler
->fd
, SOL_SOCKET
, SO_RCVBUF
,
233 &rcvbuf
,sizeof(rcvbuf
)) < 0)
236 memset(&handler
->local
, 0, sizeof(handler
->local
));
237 handler
->local
.nl_family
= AF_NETLINK
;
238 handler
->local
.nl_groups
= 0;
240 if (bind(handler
->fd
, (struct sockaddr
*)&handler
->local
,
241 sizeof(handler
->local
)) < 0)
244 socklen
= sizeof(handler
->local
);
245 if (getsockname(handler
->fd
, (struct sockaddr
*)&handler
->local
,
249 if (socklen
!= sizeof(handler
->local
))
252 if (handler
->local
.nl_family
!= AF_NETLINK
)
255 handler
->seq
= time(NULL
);
260 extern int netlink_close(struct nl_handler
*handler
)