]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/genl.c
Merge pull request #1539 from brauner/2017-05-06/fix_abstract_unix_sockets
[mirror_lxc.git] / src / lxc / genl.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
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.
13 *
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.
18 *
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
22 */
23 #include <string.h>
24 #include <stdio.h>
25 #include <sys/socket.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <linux/genetlink.h>
30 #include <linux/rtnetlink.h>
31
32 #include "nl.h"
33 #include "genl.h"
34
35 static int genetlink_resolve_family(const char *family)
36 {
37 struct nl_handler handler;
38 struct nlattr *attr;
39 struct genlmsg *request, *reply;
40 struct genlmsghdr *genlmsghdr;
41
42 int len, ret;
43
44 request = genlmsg_alloc(GENLMSG_GOOD_SIZE);
45 if (!request)
46 return -ENOMEM;
47
48 reply = genlmsg_alloc(GENLMSG_GOOD_SIZE);
49 if (!reply) {
50 genlmsg_free(request);
51 return -ENOMEM;
52 }
53
54 request->nlmsghdr.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
55 request->nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
56 request->nlmsghdr.nlmsg_type = GENL_ID_CTRL;
57
58 genlmsghdr = NLMSG_DATA(&request->nlmsghdr);
59 genlmsghdr->cmd = CTRL_CMD_GETFAMILY;
60
61 ret = netlink_open(&handler, NETLINK_GENERIC);
62 if (ret)
63 goto out;
64
65 ret = nla_put_string((struct nlmsg *)&request->nlmsghdr,
66 CTRL_ATTR_FAMILY_NAME, family);
67 if (ret)
68 goto out_close;
69
70 ret = netlink_transaction(&handler, (struct nlmsg *)&request->nlmsghdr,
71 (struct nlmsg *)&reply->nlmsghdr);
72 if (ret < 0)
73 goto out_close;
74
75 genlmsghdr = NLMSG_DATA(&reply->nlmsghdr);
76 len = reply->nlmsghdr.nlmsg_len;
77
78 ret = -ENOMSG;
79 if (reply->nlmsghdr.nlmsg_type != GENL_ID_CTRL)
80 goto out_close;
81
82 if (genlmsghdr->cmd != CTRL_CMD_NEWFAMILY)
83 goto out_close;
84
85 ret = -EMSGSIZE;
86 len -= NLMSG_LENGTH(GENL_HDRLEN);
87 if (len < 0)
88 goto out_close;
89
90 attr = (struct nlattr *)GENLMSG_DATA(reply);
91 attr = (struct nlattr *)((char *)attr + NLA_ALIGN(attr->nla_len));
92
93 ret = -ENOMSG;
94 if (attr->nla_type != CTRL_ATTR_FAMILY_ID)
95 goto out_close;
96
97 ret = *(__u16 *) NLA_DATA(attr);
98 out_close:
99 netlink_close(&handler);
100 out:
101 genlmsg_free(request);
102 genlmsg_free(reply);
103 return ret;
104 }
105
106 extern int genetlink_open(struct genl_handler *handler, const char *family)
107 {
108 int ret;
109 handler->family = genetlink_resolve_family(family);
110 if (handler->family < 0)
111 return handler->family;
112
113 ret = netlink_open(&handler->nlh, NETLINK_GENERIC);
114
115 return ret;
116 }
117
118 extern int genetlink_close(struct genl_handler *handler)
119 {
120 return netlink_close(&handler->nlh);
121 }
122
123 extern int genetlink_rcv(struct genl_handler *handler, struct genlmsg *genlmsg)
124 {
125 return netlink_rcv(&handler->nlh, (struct nlmsg *)&genlmsg->nlmsghdr);
126 }
127
128 extern int genetlink_send(struct genl_handler *handler, struct genlmsg *genlmsg)
129 {
130
131 return netlink_send(&handler->nlh, (struct nlmsg *)&genlmsg->nlmsghdr);
132 }
133
134 extern int genetlink_transaction(struct genl_handler *handler,
135 struct genlmsg *request, struct genlmsg *answer)
136 {
137 return netlink_transaction(&handler->nlh, (struct nlmsg *)&request->nlmsghdr,
138 (struct nlmsg *)&answer->nlmsghdr);
139 }
140
141 extern struct genlmsg *genlmsg_alloc(size_t size)
142 {
143 size_t len = NLMSG_LENGTH(GENL_HDRLEN) + size;
144 return (struct genlmsg *)nlmsg_alloc(len);
145 }
146
147 extern void genlmsg_free(struct genlmsg *genlmsg)
148 {
149 free(genlmsg);
150 }