chiark / gitweb /
udevd: control - no not delete socket file when --daemon is used
[elogind.git] / udev / udev-ctrl.c
1 /*
2  * libudev - interface to udev device information
3  *
4  * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  */
11
12 #include <errno.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stddef.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/poll.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22
23 #include "udev.h"
24
25 /* wire protocol magic must match */
26 #define UDEV_CTRL_MAGIC                         0xdead1dea
27
28 enum udev_ctrl_msg_type {
29         UDEV_CTRL_UNKNOWN,
30         UDEV_CTRL_SET_LOG_LEVEL,
31         UDEV_CTRL_STOP_EXEC_QUEUE,
32         UDEV_CTRL_START_EXEC_QUEUE,
33         UDEV_CTRL_RELOAD_RULES,
34         UDEV_CTRL_SET_ENV,
35         UDEV_CTRL_SET_CHILDREN_MAX,
36         UDEV_CTRL_PING,
37         UDEV_CTRL_EXIT,
38 };
39
40 struct udev_ctrl_msg_wire {
41         char version[16];
42         unsigned int magic;
43         enum udev_ctrl_msg_type type;
44         union {
45                 int intval;
46                 char buf[256];
47         };
48 };
49
50 struct udev_ctrl_msg {
51         int refcount;
52         struct udev_ctrl_connection *conn;
53         struct udev_ctrl_msg_wire ctrl_msg_wire;
54 };
55
56 struct udev_ctrl {
57         int refcount;
58         struct udev *udev;
59         int sock;
60         struct sockaddr_un saddr;
61         socklen_t addrlen;
62         bool bound;
63         bool cleanup_socket;
64         bool connected;
65 };
66
67 struct udev_ctrl_connection {
68         int refcount;
69         struct udev_ctrl *uctrl;
70         int sock;
71 };
72
73 struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd)
74 {
75         struct udev_ctrl *uctrl;
76
77         uctrl = calloc(1, sizeof(struct udev_ctrl));
78         if (uctrl == NULL)
79                 return NULL;
80         uctrl->refcount = 1;
81         uctrl->udev = udev;
82
83         if (fd < 0) {
84                 uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
85                 if (uctrl->sock < 0) {
86                         err(udev, "error getting socket: %m\n");
87                         udev_ctrl_unref(uctrl);
88                         return NULL;
89                 }
90         } else {
91                 uctrl->bound = true;
92                 uctrl->sock = fd;
93         }
94
95         uctrl->saddr.sun_family = AF_LOCAL;
96         util_strscpyl(uctrl->saddr.sun_path, sizeof(uctrl->saddr.sun_path),
97                       udev_get_run_path(udev), "/control", NULL);
98         uctrl->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(uctrl->saddr.sun_path);
99         return uctrl;
100 }
101
102 struct udev_ctrl *udev_ctrl_new(struct udev *udev)
103 {
104         return udev_ctrl_new_from_fd(udev, -1);
105 }
106
107 int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl)
108 {
109         int err;
110
111         if (!uctrl->bound) {
112                 err = bind(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen);
113                 if (err < 0 && errno == EADDRINUSE) {
114                         unlink(uctrl->saddr.sun_path);
115                         err = bind(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen);
116                 }
117
118                 if (err < 0) {
119                         err = -errno;
120                         err(uctrl->udev, "bind failed: %m\n");
121                         return err;
122                 }
123
124                 err = listen(uctrl->sock, 0);
125                 if (err < 0) {
126                         err = -errno;
127                         err(uctrl->udev, "listen failed: %m\n");
128                         return err;
129                 }
130
131                 uctrl->bound = true;
132                 uctrl->cleanup_socket = true;
133         }
134         return 0;
135 }
136
137 struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl)
138 {
139         return uctrl->udev;
140 }
141
142 struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl)
143 {
144         if (uctrl == NULL)
145                 return NULL;
146         uctrl->refcount++;
147         return uctrl;
148 }
149
150 struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl)
151 {
152         if (uctrl == NULL)
153                 return NULL;
154         uctrl->refcount--;
155         if (uctrl->refcount > 0)
156                 return uctrl;
157         if (uctrl->sock >= 0)
158                 close(uctrl->sock);
159         free(uctrl);
160         return NULL;
161 }
162
163 int udev_ctrl_cleanup(struct udev_ctrl *uctrl)
164 {
165         if (uctrl->cleanup_socket)
166                 unlink(uctrl->saddr.sun_path);
167         return 0;
168 }
169
170 int udev_ctrl_get_fd(struct udev_ctrl *uctrl)
171 {
172         if (uctrl == NULL)
173                 return -1;
174         return uctrl->sock;
175 }
176
177 struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl)
178 {
179         struct udev_ctrl_connection *conn;
180         struct ucred ucred;
181         socklen_t slen;
182         const int on = 1;
183
184         conn = calloc(1, sizeof(struct udev_ctrl_connection));
185         if (conn == NULL)
186                 return NULL;
187         conn->refcount = 1;
188         conn->uctrl = uctrl;
189
190         conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
191         if (conn->sock < 0) {
192                 if (errno != EINTR)
193                         err(uctrl->udev, "unable to receive ctrl connection: %m\n");
194                 goto err;
195         }
196
197         /* check peer credential of connection */
198         slen = sizeof(ucred);
199         if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED, &ucred, &slen) < 0) {
200                 err(uctrl->udev, "unable to receive credentials of ctrl connection: %m\n");
201                 goto err;
202         }
203         if (ucred.uid > 0) {
204                 err(uctrl->udev, "sender uid=%i, message ignored\n", ucred.uid);
205                 goto err;
206         }
207
208         /* enable receiving of the sender credentials in the messages */
209         setsockopt(conn->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
210         udev_ctrl_ref(uctrl);
211         return conn;
212 err:
213         if (conn->sock >= 0)
214                 close(conn->sock);
215         free(conn);
216         return NULL;
217 }
218
219 struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn)
220 {
221         if (conn == NULL)
222                 return NULL;
223         conn->refcount++;
224         return conn;
225 }
226
227 struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn)
228 {
229         if (conn == NULL)
230                 return NULL;
231         conn->refcount--;
232         if (conn->refcount > 0)
233                 return conn;
234         if (conn->sock >= 0)
235                 close(conn->sock);
236         udev_ctrl_unref(conn->uctrl);
237         free(conn);
238         return NULL;
239 }
240
241 static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout)
242 {
243         struct udev_ctrl_msg_wire ctrl_msg_wire;
244         int err = 0;
245
246         memset(&ctrl_msg_wire, 0x00, sizeof(struct udev_ctrl_msg_wire));
247         strcpy(ctrl_msg_wire.version, "udev-" VERSION);
248         ctrl_msg_wire.magic = UDEV_CTRL_MAGIC;
249         ctrl_msg_wire.type = type;
250
251         if (buf != NULL)
252                 util_strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf);
253         else
254                 ctrl_msg_wire.intval = intval;
255
256         if (!uctrl->connected) {
257                 if (connect(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen) < 0) {
258                         err = -errno;
259                         goto out;
260                 }
261                 uctrl->connected = true;
262         }
263         if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0) {
264                 err = -errno;
265                 goto out;
266         }
267
268         /* wait for peer message handling or disconnect */
269         for (;;) {
270                 struct pollfd pfd[1];
271                 int r;
272
273                 pfd[0].fd = uctrl->sock;
274                 pfd[0].events = POLLIN;
275                 r = poll(pfd, 1, timeout * 1000);
276                 if (r  < 0) {
277                         if (errno == EINTR)
278                                 continue;
279                         err = -errno;
280                         break;
281                 }
282
283                 if (r > 0 && pfd[0].revents & POLLERR) {
284                         err = -EIO;
285                         break;
286                 }
287
288                 if (r == 0)
289                         err = -ETIMEDOUT;
290                 break;
291         }
292 out:
293         return err;
294 }
295
296 int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout)
297 {
298         return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout);
299 }
300
301 int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout)
302 {
303         return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout);
304 }
305
306 int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout)
307 {
308         return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout);
309 }
310
311 int udev_ctrl_send_reload_rules(struct udev_ctrl *uctrl, int timeout)
312 {
313         return ctrl_send(uctrl, UDEV_CTRL_RELOAD_RULES, 0, NULL, timeout);
314 }
315
316 int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout)
317 {
318         return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout);
319 }
320
321 int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout)
322 {
323         return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout);
324 }
325
326 int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout)
327 {
328         return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout);
329 }
330
331 int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout)
332 {
333         return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout);
334 }
335
336 struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn)
337 {
338         struct udev *udev = conn->uctrl->udev;
339         struct udev_ctrl_msg *uctrl_msg;
340         ssize_t size;
341         struct msghdr smsg;
342         struct cmsghdr *cmsg;
343         struct iovec iov;
344         struct ucred *cred;
345         char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
346
347         uctrl_msg = calloc(1, sizeof(struct udev_ctrl_msg));
348         if (uctrl_msg == NULL)
349                 return NULL;
350         uctrl_msg->refcount = 1;
351         uctrl_msg->conn = conn;
352         udev_ctrl_connection_ref(conn);
353
354         /* wait for the incoming message */
355         for(;;) {
356                 struct pollfd pfd[1];
357                 int r;
358
359                 pfd[0].fd = conn->sock;
360                 pfd[0].events = POLLIN;
361
362                 r = poll(pfd, 1, 10000);
363                 if (r  < 0) {
364                         if (errno == EINTR)
365                                 continue;
366                         goto err;
367                 } else if (r == 0) {
368                         err(udev, "timeout waiting for ctrl message\n");
369                         goto err;
370                 } else {
371                         if (!(pfd[0].revents & POLLIN)) {
372                                 err(udev, "ctrl connection error: %m\n");
373                                 goto err;
374                         }
375                 }
376
377                 break;
378         }
379
380         iov.iov_base = &uctrl_msg->ctrl_msg_wire;
381         iov.iov_len = sizeof(struct udev_ctrl_msg_wire);
382         memset(&smsg, 0x00, sizeof(struct msghdr));
383         smsg.msg_iov = &iov;
384         smsg.msg_iovlen = 1;
385         smsg.msg_control = cred_msg;
386         smsg.msg_controllen = sizeof(cred_msg);
387         size = recvmsg(conn->sock, &smsg, 0);
388         if (size <  0) {
389                 err(udev, "unable to receive ctrl message: %m\n");
390                 goto err;
391         }
392         cmsg = CMSG_FIRSTHDR(&smsg);
393         cred = (struct ucred *) CMSG_DATA(cmsg);
394
395         if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
396                 err(udev, "no sender credentials received, message ignored\n");
397                 goto err;
398         }
399
400         if (cred->uid != 0) {
401                 err(udev, "sender uid=%i, message ignored\n", cred->uid);
402                 goto err;
403         }
404
405         if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) {
406                 err(udev, "message magic 0x%08x doesn't match, ignore it\n", uctrl_msg->ctrl_msg_wire.magic);
407                 goto err;
408         }
409
410         dbg(udev, "created ctrl_msg %p (%i)\n", uctrl_msg, uctrl_msg->ctrl_msg_wire.type);
411         return uctrl_msg;
412 err:
413         udev_ctrl_msg_unref(uctrl_msg);
414         return NULL;
415 }
416
417 struct udev_ctrl_msg *udev_ctrl_msg_ref(struct udev_ctrl_msg *ctrl_msg)
418 {
419         if (ctrl_msg == NULL)
420                 return NULL;
421         ctrl_msg->refcount++;
422         return ctrl_msg;
423 }
424
425 struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg)
426 {
427         if (ctrl_msg == NULL)
428                 return NULL;
429         ctrl_msg->refcount--;
430         if (ctrl_msg->refcount > 0)
431                 return ctrl_msg;
432         dbg(ctrl_msg->conn->uctrl->udev, "release ctrl_msg %p\n", ctrl_msg);
433         udev_ctrl_connection_unref(ctrl_msg->conn);
434         free(ctrl_msg);
435         return NULL;
436 }
437
438 int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg)
439 {
440         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL)
441                 return ctrl_msg->ctrl_msg_wire.intval;
442         return -1;
443 }
444
445 int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg)
446 {
447         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_STOP_EXEC_QUEUE)
448                 return 1;
449         return -1;
450 }
451
452 int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg)
453 {
454         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_START_EXEC_QUEUE)
455                 return 1;
456         return -1;
457 }
458
459 int udev_ctrl_get_reload_rules(struct udev_ctrl_msg *ctrl_msg)
460 {
461         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_RELOAD_RULES)
462                 return 1;
463         return -1;
464 }
465
466 const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg)
467 {
468         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_ENV)
469                 return ctrl_msg->ctrl_msg_wire.buf;
470         return NULL;
471 }
472
473 int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg)
474 {
475         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_CHILDREN_MAX)
476                 return ctrl_msg->ctrl_msg_wire.intval;
477         return -1;
478 }
479
480 int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg)
481 {
482         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_PING)
483                 return 1;
484         return -1;
485 }
486
487 int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg)
488 {
489         if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_EXIT)
490                 return 1;
491         return -1;
492 }