2
#include <acpid/driver/netlink.h>
5
* low-level netlink functions
8
int netlink_open(struct acpi_channel_private *private, int protocol, int groups)
10
private->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
14
memset(&private->local, 0, sizeof(private->local));
15
private->local.nl_family = AF_NETLINK;
16
private->local.nl_groups = groups;
18
if (bind(private->fd, (struct sockaddr *)&private->local, sizeof(private->local)) < 0)
21
socklen_t len = sizeof(private->local);
22
if (getsockname(private->fd, (struct sockaddr *)&private->local, &len) < 0)
25
private->seq = time(NULL);
34
int netlink_send(struct acpi_channel_private *private, struct nlmsghdr *n, pid_t peer, int groups)
36
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK, .nl_pid = peer, .nl_groups = groups };
38
n->nlmsg_seq = ++private->seq;
39
return sendto(private->fd, n, n->nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(nladdr));
42
int netlink_recv(struct acpi_channel_private *private, struct nlmsghdr *n, pid_t *peer)
44
struct sockaddr_nl nladdr;
45
socklen_t len = sizeof(nladdr);
47
int ret = recvfrom(private->fd, n, n->nlmsg_len, 0, (struct sockaddr *)&nladdr, &len);
48
*peer = nladdr.nl_pid;
53
int netlink_wait(struct acpi_channel_private *private, struct nlmsghdr *n, pid_t peer)
55
int len = n->nlmsg_len;
61
int ret = netlink_recv(private, n, &sender);
62
if (ret < 0 || sender != peer)
65
for (struct nlmsghdr * h = n; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
66
if (h->nlmsg_pid != private->local.nl_pid || h->nlmsg_seq != private->seq)
69
if (h->nlmsg_type == NLMSG_ERROR)
72
memcpy(n, h, h->nlmsg_len);
78
void netlink_close(struct acpi_channel_private *private)
84
* netlink message attributes
87
int netlink_attr_attach(struct nlmsghdr *n, int max, int type, const void *data, int alen)
89
int len = NLA_LENGTH(alen);
92
if (NLMSG_ALIGN(n->nlmsg_len) + NLA_ALIGN(len) > max)
98
memcpy(NLA_DATA(nla), data, alen);
99
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLA_ALIGN(len);
103
int netlink_attr_parse(struct nlattr *table[], int max, struct nlattr *src, int len)
105
memset(table, 0, sizeof(struct nlattr *) * (max + 1));
107
while (NLA_OK(src, len)) {
108
if (src->nla_type <= max)
109
table[src->nla_type] = src;
110
src = NLA_NEXT(src, len);
117
* acpi netlink broadcast group discovery
120
static const char *acpi_family_name = "acpi_event";
121
static const char *acpi_group_name = "acpi_mc_group";
123
static int acapi_netlink_group(struct nlattr *attr, int *group)
128
struct nlattr *attrs[CTRL_ATTR_MCAST_GRP_MAX + 1];
129
netlink_attr_parse(attrs, CTRL_ATTR_MCAST_GRP_MAX, NLA_DATA(attr), attr->nla_len - NLA_HDRLEN);
131
const char *name = NLA_DATA(attrs[CTRL_ATTR_MCAST_GRP_NAME]);
132
if (strcmp(name, acpi_group_name))
135
*group = *(__u32 *) (NLA_DATA(attrs[CTRL_ATTR_MCAST_GRP_ID]));
140
static int acpi_netlink_family(struct nlmsghdr *n, int *family, int *group)
142
if (n->nlmsg_type != GENL_ID_CTRL)
144
struct genlmsghdr *ghdr = NLMSG_DATA(n);
146
if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
149
if (n->nlmsg_len < NLMSG_LENGTH(GENL_HDRLEN))
152
struct nlattr *attrs[CTRL_ATTR_MAX + 1];
153
netlink_attr_parse(attrs, CTRL_ATTR_MAX, NLMSG_DATA(n) + GENL_HDRLEN, NLMSG_PAYLOAD(n, GENL_HDRLEN));
155
if (attrs[CTRL_ATTR_FAMILY_ID])
156
*family = *(__u32 *) (NLA_DATA(attrs[CTRL_ATTR_FAMILY_ID]));
158
if (attrs[CTRL_ATTR_MCAST_GROUPS]) {
159
struct nlattr *attrs2[GENL_MAX_FAM_GRPS + 1];
160
netlink_attr_parse(attrs2, GENL_MAX_FAM_GRPS, NLA_DATA(attrs[CTRL_ATTR_MCAST_GROUPS]), attrs[CTRL_ATTR_MCAST_GROUPS]->nla_len - NLA_HDRLEN);
162
for (int i = 0; i < GENL_MAX_FAM_GRPS; i++) {
163
if (acapi_netlink_group(attrs2[i], group) == 0)
171
int acpi_netlink_event(struct acpi_channel *channel, struct acpi_genl_event *events, int max)
173
struct acpi_channel_private *private = channel->private;
176
struct nlmsghdr *n = (struct nlmsghdr *) &buffer;
180
int ret = netlink_recv(private, n, &sender);
185
for (struct nlmsghdr * h = n; NLMSG_OK(h, ret) && i < max; h = NLMSG_NEXT(h, ret), ++i) {
186
if (h->nlmsg_type == NLMSG_ERROR)
189
struct nlattr *attrs[ACPI_GENL_ATTR_MAX + 1];
190
netlink_attr_parse(attrs, ACPI_GENL_ATTR_MAX, NLMSG_DATA(h) + GENL_HDRLEN, NLMSG_PAYLOAD(h, GENL_HDRLEN));
192
if (attrs[ACPI_GENL_ATTR_EVENT]) {
193
struct acpi_genl_event *event = NLA_DATA(attrs[ACPI_GENL_ATTR_EVENT]);
194
memcpy(events + i, event, sizeof(struct acpi_genl_event));
204
* acpi netlink channel
207
static int setup(struct acpi_channel *channel, struct acpi_channel_descriptor *cds, unsigned long num)
209
struct acpi_channel_private *private = (struct acpi_channel_private *) channel->private;
211
acpi_channel_watch(channel, cds, private->fd, POLLIN);
216
static int handle(struct acpi_channel *channel, lua_State *L, int fd, int events)
218
struct acpi_channel_private *private = channel->private;
221
struct acpi_genl_event e;
222
int ret = acpi_netlink_event(channel, &e, 1);
226
printf("got event: %20s %15s %08x %08x\n", e.device_class, e.bus_id, e.type, e.data);
228
//*strchr(e.bus_id, ':') = 0;
229
acpi_channel_event(channel, L, e.bus_id, e.type, e.data);
236
static int create(struct acpi_channel *channel, lua_State *L)
238
static const struct acpi_channel_ops ops = { setup, handle };
239
acpi_channel_register(channel, &ops);
241
lua_pushinteger(L, 1);
243
int ret = strcmp(lua_tostring(L, -1), "acpi");
249
channel->private = malloc(sizeof(struct acpi_channel_private));
250
if (channel->private == NULL)
253
struct acpi_channel_private *private = channel->private;
254
if (netlink_open(private, NETLINK_GENERIC, 0))
258
struct nlmsghdr *nlmsg = (struct nlmsghdr *)&buffer;
260
nlmsg->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
261
nlmsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
262
nlmsg->nlmsg_type = GENL_ID_CTRL;
264
struct genlmsghdr *ghdr = NLMSG_DATA(nlmsg);
265
ghdr->cmd = CTRL_CMD_GETFAMILY;
267
netlink_attr_attach(nlmsg, 128, CTRL_ATTR_FAMILY_NAME, acpi_family_name, strlen(acpi_family_name) + 1);
269
if (netlink_send(private, nlmsg, 0, 0) < 0)
272
nlmsg->nlmsg_len = 256;
273
if (netlink_wait(private, nlmsg, 0) < 0)
277
if (acpi_netlink_family(nlmsg, &family, &group) < 0)
280
netlink_close(private);
281
if (netlink_open(private, NETLINK_GENERIC, group ? (1 << (group - 1)) : 0))
284
int flags = fcntl(private->fd, F_GETFL, 0);
285
fcntl(private->fd, F_SETFL, flags | O_NONBLOCK);
290
netlink_close(private);
294
static void destroy(struct acpi_channel *channel)
296
struct acpi_channel_private *private = channel->private;
299
free(channel->private);
308
static __attribute__((constructor)) void constructor()
310
static const struct acpi_driver driver = { "netlink", { create, destroy } };
311
acpi_driver_register(&driver);