summaryrefslogtreecommitdiff
path: root/src/socket-util.c
diff options
context:
space:
mode:
authorFabiano Fidencio <fidencio@profusion.mobi>2010-09-20 16:33:14 -0300
committerLennart Poettering <lennart@poettering.net>2010-09-21 01:00:38 +0200
commit5bfcc1c6ef48af20996412dbaac1daa0492a4d41 (patch)
treecd8831c84f81bb550242e351998f0f6efcbb8e1f /src/socket-util.c
parent918f4c69fabadc328b5ca3bbd9eb73c3e486e103 (diff)
socket: Support IPv6-less systems with runtime check.
This patch introduces socket_ipv6_is_supported() call that checks for IPv6 availability. Code then check for it before using specific calls. In order to be less intrusive, this patch avoids IPv6 entries being parsed at all, this way we don't get such entries in the system and all other code paths are automatically ignored. However an extra check is done at socket_address_listen() to make sure of that. As the number of Netlink messages is not know upfront anymore, loopback-setup.c was refactored to dynamically calculate the sequence number and count. Lennart's suggestions were fixed and squashed with the original patch, that was sent by Gustavo Sverzut Barbieri (barbieri@profusion.mobi).
Diffstat (limited to 'src/socket-util.c')
-rw-r--r--src/socket-util.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/src/socket-util.c b/src/socket-util.c
index 151757c52b..3f4d65a4c8 100644
--- a/src/socket-util.c
+++ b/src/socket-util.c
@@ -35,6 +35,7 @@
#include "socket-util.h"
#include "missing.h"
#include "label.h"
+#include <sys/ioctl.h>
int socket_address_parse(SocketAddress *a, const char *s) {
int r;
@@ -50,6 +51,11 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (*s == '[') {
/* IPv6 in [x:.....:z]:p notation */
+ if (!socket_ipv6_is_supported()) {
+ log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
+ return -EAFNOSUPPORT;
+ }
+
if (!(e = strchr(s+1, ']')))
return -EINVAL;
@@ -145,12 +151,16 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (idx == 0)
return -EINVAL;
+ if (!socket_ipv6_is_supported()) {
+ log_warning("Binding to interface is not available since kernel does not support IPv6.");
+ return -EAFNOSUPPORT;
+ }
+
a->sockaddr.in6.sin6_family = AF_INET6;
a->sockaddr.in6.sin6_port = htons((uint16_t) u);
a->sockaddr.in6.sin6_scope_id = idx;
a->sockaddr.in6.sin6_addr = in6addr_any;
a->size = sizeof(struct sockaddr_in6);
-
}
} else {
@@ -161,10 +171,17 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (u <= 0 || u > 0xFFFF)
return -EINVAL;
- a->sockaddr.in6.sin6_family = AF_INET6;
- a->sockaddr.in6.sin6_port = htons((uint16_t) u);
- a->sockaddr.in6.sin6_addr = in6addr_any;
- a->size = sizeof(struct sockaddr_in6);
+ if (socket_ipv6_is_supported()) {
+ a->sockaddr.in6.sin6_family = AF_INET6;
+ a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+ a->sockaddr.in6.sin6_addr = in6addr_any;
+ a->size = sizeof(struct sockaddr_in6);
+ } else {
+ a->sockaddr.in4.sin_family = AF_INET;
+ a->sockaddr.in4.sin_port = htons((uint16_t) u);
+ a->sockaddr.in4.sin_addr.s_addr = INADDR_ANY;
+ a->size = sizeof(struct sockaddr_in);
+ }
}
}
@@ -316,6 +333,9 @@ int socket_address_listen(
if ((r = socket_address_verify(a)) < 0)
return r;
+ if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported())
+ return -EAFNOSUPPORT;
+
r = label_socket_set(label);
if (r < 0)
return r;
@@ -484,6 +504,10 @@ bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) {
return path_startswith(a->sockaddr.un.sun_path, prefix);
}
+bool socket_ipv6_is_supported(void) {
+ return access("/sys/module/ipv6", F_OK) == 0;
+}
+
static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
[SOCKET_ADDRESS_DEFAULT] = "default",
[SOCKET_ADDRESS_BOTH] = "both",