]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/socket-util.c
udev: set errno = ENOSYS for removed interfaces
[thirdparty/systemd.git] / src / shared / socket-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <arpa/inet.h>
28 #include <stdio.h>
29 #include <net/if.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stddef.h>
33 #include <sys/ioctl.h>
34
35 #include "macro.h"
36 #include "util.h"
37 #include "socket-util.h"
38 #include "missing.h"
39 #include "label.h"
40
41 int socket_address_parse(SocketAddress *a, const char *s) {
42 int r;
43 char *e, *n;
44 unsigned u;
45
46 assert(a);
47 assert(s);
48
49 zero(*a);
50 a->type = SOCK_STREAM;
51
52 if (*s == '[') {
53 /* IPv6 in [x:.....:z]:p notation */
54
55 if (!socket_ipv6_is_supported()) {
56 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
57 return -EAFNOSUPPORT;
58 }
59
60 if (!(e = strchr(s+1, ']')))
61 return -EINVAL;
62
63 if (!(n = strndup(s+1, e-s-1)))
64 return -ENOMEM;
65
66 errno = 0;
67 if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) {
68 free(n);
69 return errno != 0 ? -errno : -EINVAL;
70 }
71
72 free(n);
73
74 e++;
75 if (*e != ':')
76 return -EINVAL;
77
78 e++;
79 if ((r = safe_atou(e, &u)) < 0)
80 return r;
81
82 if (u <= 0 || u > 0xFFFF)
83 return -EINVAL;
84
85 a->sockaddr.in6.sin6_family = AF_INET6;
86 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
87 a->size = sizeof(struct sockaddr_in6);
88
89 } else if (*s == '/') {
90 /* AF_UNIX socket */
91
92 size_t l;
93
94 l = strlen(s);
95 if (l >= sizeof(a->sockaddr.un.sun_path))
96 return -EINVAL;
97
98 a->sockaddr.un.sun_family = AF_UNIX;
99 memcpy(a->sockaddr.un.sun_path, s, l);
100 a->size = offsetof(struct sockaddr_un, sun_path) + l + 1;
101
102 } else if (*s == '@') {
103 /* Abstract AF_UNIX socket */
104 size_t l;
105
106 l = strlen(s+1);
107 if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
108 return -EINVAL;
109
110 a->sockaddr.un.sun_family = AF_UNIX;
111 memcpy(a->sockaddr.un.sun_path+1, s+1, l);
112 a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
113
114 } else {
115
116 if ((e = strchr(s, ':'))) {
117
118 if ((r = safe_atou(e+1, &u)) < 0)
119 return r;
120
121 if (u <= 0 || u > 0xFFFF)
122 return -EINVAL;
123
124 if (!(n = strndup(s, e-s)))
125 return -ENOMEM;
126
127 /* IPv4 in w.x.y.z:p notation? */
128 if ((r = inet_pton(AF_INET, n, &a->sockaddr.in4.sin_addr)) < 0) {
129 free(n);
130 return -errno;
131 }
132
133 if (r > 0) {
134 /* Gotcha, it's a traditional IPv4 address */
135 free(n);
136
137 a->sockaddr.in4.sin_family = AF_INET;
138 a->sockaddr.in4.sin_port = htons((uint16_t) u);
139 a->size = sizeof(struct sockaddr_in);
140 } else {
141 unsigned idx;
142
143 if (strlen(n) > IF_NAMESIZE-1) {
144 free(n);
145 return -EINVAL;
146 }
147
148 /* Uh, our last resort, an interface name */
149 idx = if_nametoindex(n);
150 free(n);
151
152 if (idx == 0)
153 return -EINVAL;
154
155 if (!socket_ipv6_is_supported()) {
156 log_warning("Binding to interface is not available since kernel does not support IPv6.");
157 return -EAFNOSUPPORT;
158 }
159
160 a->sockaddr.in6.sin6_family = AF_INET6;
161 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
162 a->sockaddr.in6.sin6_scope_id = idx;
163 a->sockaddr.in6.sin6_addr = in6addr_any;
164 a->size = sizeof(struct sockaddr_in6);
165 }
166 } else {
167
168 /* Just a port */
169 if ((r = safe_atou(s, &u)) < 0)
170 return r;
171
172 if (u <= 0 || u > 0xFFFF)
173 return -EINVAL;
174
175 if (socket_ipv6_is_supported()) {
176 a->sockaddr.in6.sin6_family = AF_INET6;
177 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
178 a->sockaddr.in6.sin6_addr = in6addr_any;
179 a->size = sizeof(struct sockaddr_in6);
180 } else {
181 a->sockaddr.in4.sin_family = AF_INET;
182 a->sockaddr.in4.sin_port = htons((uint16_t) u);
183 a->sockaddr.in4.sin_addr.s_addr = INADDR_ANY;
184 a->size = sizeof(struct sockaddr_in);
185 }
186 }
187 }
188
189 return 0;
190 }
191
192 int socket_address_parse_netlink(SocketAddress *a, const char *s) {
193 int family;
194 unsigned group = 0;
195 char* sfamily = NULL;
196 assert(a);
197 assert(s);
198
199 zero(*a);
200 a->type = SOCK_RAW;
201
202 errno = 0;
203 if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
204 return errno ? -errno : -EINVAL;
205
206 if ((family = netlink_family_from_string(sfamily)) < 0)
207 if (safe_atoi(sfamily, &family) < 0) {
208 free(sfamily);
209 return -EINVAL;
210 }
211
212 free(sfamily);
213
214 a->sockaddr.nl.nl_family = AF_NETLINK;
215 a->sockaddr.nl.nl_groups = group;
216
217 a->type = SOCK_RAW;
218 a->size = sizeof(struct sockaddr_nl);
219 a->protocol = family;
220
221 return 0;
222 }
223
224 int socket_address_verify(const SocketAddress *a) {
225 assert(a);
226
227 switch (socket_address_family(a)) {
228
229 case AF_INET:
230 if (a->size != sizeof(struct sockaddr_in))
231 return -EINVAL;
232
233 if (a->sockaddr.in4.sin_port == 0)
234 return -EINVAL;
235
236 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
237 return -EINVAL;
238
239 return 0;
240
241 case AF_INET6:
242 if (a->size != sizeof(struct sockaddr_in6))
243 return -EINVAL;
244
245 if (a->sockaddr.in6.sin6_port == 0)
246 return -EINVAL;
247
248 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
249 return -EINVAL;
250
251 return 0;
252
253 case AF_UNIX:
254 if (a->size < offsetof(struct sockaddr_un, sun_path))
255 return -EINVAL;
256
257 if (a->size > offsetof(struct sockaddr_un, sun_path)) {
258
259 if (a->sockaddr.un.sun_path[0] != 0) {
260 char *e;
261
262 /* path */
263 if (!(e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path))))
264 return -EINVAL;
265
266 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
267 return -EINVAL;
268 }
269 }
270
271 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
272 return -EINVAL;
273
274 return 0;
275
276 case AF_NETLINK:
277
278 if (a->size != sizeof(struct sockaddr_nl))
279 return -EINVAL;
280
281 if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
282 return -EINVAL;
283
284 return 0;
285
286 default:
287 return -EAFNOSUPPORT;
288 }
289 }
290
291 int socket_address_print(const SocketAddress *a, char **p) {
292 int r;
293 assert(a);
294 assert(p);
295
296 if ((r = socket_address_verify(a)) < 0)
297 return r;
298
299 switch (socket_address_family(a)) {
300
301 case AF_INET: {
302 char *ret;
303
304 if (!(ret = new(char, INET_ADDRSTRLEN+1+5+1)))
305 return -ENOMEM;
306
307 if (!inet_ntop(AF_INET, &a->sockaddr.in4.sin_addr, ret, INET_ADDRSTRLEN)) {
308 free(ret);
309 return -errno;
310 }
311
312 sprintf(strchr(ret, 0), ":%u", ntohs(a->sockaddr.in4.sin_port));
313 *p = ret;
314 return 0;
315 }
316
317 case AF_INET6: {
318 char *ret;
319
320 if (!(ret = new(char, 1+INET6_ADDRSTRLEN+2+5+1)))
321 return -ENOMEM;
322
323 ret[0] = '[';
324 if (!inet_ntop(AF_INET6, &a->sockaddr.in6.sin6_addr, ret+1, INET6_ADDRSTRLEN)) {
325 free(ret);
326 return -errno;
327 }
328
329 sprintf(strchr(ret, 0), "]:%u", ntohs(a->sockaddr.in6.sin6_port));
330 *p = ret;
331 return 0;
332 }
333
334 case AF_UNIX: {
335 char *ret;
336
337 if (a->size <= offsetof(struct sockaddr_un, sun_path)) {
338
339 if (!(ret = strdup("<unnamed>")))
340 return -ENOMEM;
341
342 } else if (a->sockaddr.un.sun_path[0] == 0) {
343 /* abstract */
344
345 /* FIXME: We assume we can print the
346 * socket path here and that it hasn't
347 * more than one NUL byte. That is
348 * actually an invalid assumption */
349
350 if (!(ret = new(char, sizeof(a->sockaddr.un.sun_path)+1)))
351 return -ENOMEM;
352
353 ret[0] = '@';
354 memcpy(ret+1, a->sockaddr.un.sun_path+1, sizeof(a->sockaddr.un.sun_path)-1);
355 ret[sizeof(a->sockaddr.un.sun_path)] = 0;
356
357 } else {
358
359 if (!(ret = strdup(a->sockaddr.un.sun_path)))
360 return -ENOMEM;
361 }
362
363 *p = ret;
364 return 0;
365 }
366
367 case AF_NETLINK: {
368 const char *sfamily;
369
370 if ((sfamily = netlink_family_to_string(a->protocol)))
371 r = asprintf(p, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
372 else
373 r = asprintf(p, "%i %u", a->protocol, a->sockaddr.nl.nl_groups);
374
375 if (r < 0)
376 return -ENOMEM;
377
378 return 0;
379 }
380
381 default:
382 return -EINVAL;
383 }
384 }
385
386 int socket_address_listen(
387 const SocketAddress *a,
388 int backlog,
389 SocketAddressBindIPv6Only only,
390 const char *bind_to_device,
391 bool free_bind,
392 bool transparent,
393 mode_t directory_mode,
394 mode_t socket_mode,
395 const char *label,
396 int *ret) {
397
398 int r, fd, one;
399 assert(a);
400 assert(ret);
401
402 if ((r = socket_address_verify(a)) < 0)
403 return r;
404
405 if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported())
406 return -EAFNOSUPPORT;
407
408 r = label_socket_set(label);
409 if (r < 0)
410 return r;
411
412 fd = socket(socket_address_family(a), a->type | SOCK_NONBLOCK | SOCK_CLOEXEC, a->protocol);
413 r = fd < 0 ? -errno : 0;
414
415 label_socket_clear();
416
417 if (r < 0)
418 return r;
419
420 if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) {
421 int flag = only == SOCKET_ADDRESS_IPV6_ONLY;
422
423 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0)
424 goto fail;
425 }
426
427 if (socket_address_family(a) == AF_INET || socket_address_family(a) == AF_INET6) {
428 if (bind_to_device)
429 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
430 goto fail;
431
432 if (free_bind) {
433 one = 1;
434 if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
435 log_warning("IP_FREEBIND failed: %m");
436 }
437
438 if (transparent) {
439 one = 1;
440 if (setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0)
441 log_warning("IP_TRANSPARENT failed: %m");
442 }
443 }
444
445 one = 1;
446 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
447 goto fail;
448
449 if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
450 mode_t old_mask;
451
452 /* Create parents */
453 mkdir_parents(a->sockaddr.un.sun_path, directory_mode);
454
455 /* Enforce the right access mode for the socket*/
456 old_mask = umask(~ socket_mode);
457
458 /* Include the original umask in our mask */
459 umask(~socket_mode | old_mask);
460
461 r = label_bind(fd, &a->sockaddr.sa, a->size);
462
463 if (r < 0 && errno == EADDRINUSE) {
464 /* Unlink and try again */
465 unlink(a->sockaddr.un.sun_path);
466 r = bind(fd, &a->sockaddr.sa, a->size);
467 }
468
469 umask(old_mask);
470 } else
471 r = bind(fd, &a->sockaddr.sa, a->size);
472
473 if (r < 0)
474 goto fail;
475
476 if (socket_address_can_accept(a))
477 if (listen(fd, backlog) < 0)
478 goto fail;
479
480 *ret = fd;
481 return 0;
482
483 fail:
484 r = -errno;
485 close_nointr_nofail(fd);
486 return r;
487 }
488
489 bool socket_address_can_accept(const SocketAddress *a) {
490 assert(a);
491
492 return
493 a->type == SOCK_STREAM ||
494 a->type == SOCK_SEQPACKET;
495 }
496
497 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
498 assert(a);
499 assert(b);
500
501 /* Invalid addresses are unequal to all */
502 if (socket_address_verify(a) < 0 ||
503 socket_address_verify(b) < 0)
504 return false;
505
506 if (a->type != b->type)
507 return false;
508
509 if (a->size != b->size)
510 return false;
511
512 if (socket_address_family(a) != socket_address_family(b))
513 return false;
514
515 switch (socket_address_family(a)) {
516
517 case AF_INET:
518 if (a->sockaddr.in4.sin_addr.s_addr != b->sockaddr.in4.sin_addr.s_addr)
519 return false;
520
521 if (a->sockaddr.in4.sin_port != b->sockaddr.in4.sin_port)
522 return false;
523
524 break;
525
526 case AF_INET6:
527 if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
528 return false;
529
530 if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
531 return false;
532
533 break;
534
535 case AF_UNIX:
536
537 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
538 return false;
539
540 if (a->sockaddr.un.sun_path[0]) {
541 if (strncmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, sizeof(a->sockaddr.un.sun_path)) != 0)
542 return false;
543 } else {
544 if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
545 return false;
546 }
547
548 break;
549
550 case AF_NETLINK:
551
552 if (a->protocol != b->protocol)
553 return false;
554
555 if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
556 return false;
557
558 break;
559
560 default:
561 /* Cannot compare, so we assume the addresses are different */
562 return false;
563 }
564
565 return true;
566 }
567
568 bool socket_address_is(const SocketAddress *a, const char *s, int type) {
569 struct SocketAddress b;
570
571 assert(a);
572 assert(s);
573
574 if (socket_address_parse(&b, s) < 0)
575 return false;
576
577 b.type = type;
578
579 return socket_address_equal(a, &b);
580 }
581
582 bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
583 struct SocketAddress b;
584
585 assert(a);
586 assert(s);
587
588 if (socket_address_parse_netlink(&b, s) < 0)
589 return false;
590
591 return socket_address_equal(a, &b);
592 }
593
594 bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) {
595 assert(a);
596
597 if (socket_address_family(a) != AF_UNIX)
598 return false;
599
600 if (a->sockaddr.un.sun_path[0] == 0)
601 return false;
602
603 return path_startswith(a->sockaddr.un.sun_path, prefix);
604 }
605
606 bool socket_ipv6_is_supported(void) {
607 char *l = 0;
608 bool enabled;
609
610 if (access("/sys/module/ipv6", F_OK) != 0)
611 return 0;
612
613 /* If we can't check "disable" parameter, assume enabled */
614 if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
615 return 1;
616
617 /* If module was loaded with disable=1 no IPv6 available */
618 enabled = l[0] == '0';
619 free(l);
620
621 return enabled;
622 }
623
624 static const char* const netlink_family_table[] = {
625 [NETLINK_ROUTE] = "route",
626 [NETLINK_FIREWALL] = "firewall",
627 [NETLINK_INET_DIAG] = "inet-diag",
628 [NETLINK_NFLOG] = "nflog",
629 [NETLINK_XFRM] = "xfrm",
630 [NETLINK_SELINUX] = "selinux",
631 [NETLINK_ISCSI] = "iscsi",
632 [NETLINK_AUDIT] = "audit",
633 [NETLINK_FIB_LOOKUP] = "fib-lookup",
634 [NETLINK_CONNECTOR] = "connector",
635 [NETLINK_NETFILTER] = "netfilter",
636 [NETLINK_IP6_FW] = "ip6-fw",
637 [NETLINK_DNRTMSG] = "dnrtmsg",
638 [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
639 [NETLINK_GENERIC] = "generic",
640 [NETLINK_SCSITRANSPORT] = "scsitransport",
641 [NETLINK_ECRYPTFS] = "ecryptfs"
642 };
643
644 DEFINE_STRING_TABLE_LOOKUP(netlink_family, int);
645
646 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
647 [SOCKET_ADDRESS_DEFAULT] = "default",
648 [SOCKET_ADDRESS_BOTH] = "both",
649 [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
650 };
651
652 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);