chiark / gitweb /
sysctl.d, binfmt.d, modules-load.d: switch to stacked config dirs in /lib, /etc,...
[elogind.git] / src / loopback-setup.c
index e37bf4190bd010d2207130952d48d447f6f80b05..b6359def7fce60df73d6f4d8791f0ade31fef623 100644 (file)
@@ -1,4 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 
 /***
   This file is part of systemd.
 #include "util.h"
 #include "macro.h"
 #include "loopback-setup.h"
-
-enum {
-        REQUEST_NONE = 0,
-        REQUEST_ADDRESS_IPV4 = 1,
-        REQUEST_ADDRESS_IPV6 = 2,
-        REQUEST_FLAGS = 4,
-        REQUEST_ALL = 7
-};
+#include "socket-util.h"
 
 #define NLMSG_TAIL(nmsg)                                                \
         ((struct rtattr *) (((uint8_t*) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
@@ -89,7 +82,7 @@ static ssize_t recvfrom_loop(int fd, void *buf, size_t buf_len, int flags, struc
         }
 }
 
-static int add_adresses(int fd, int if_loopback) {
+static int add_adresses(int fd, int if_loopback, unsigned *requests) {
         union {
                 struct sockaddr sa;
                 struct sockaddr_nl nl;
@@ -110,7 +103,7 @@ static int add_adresses(int fd, int if_loopback) {
         request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
         request.header.nlmsg_type = RTM_NEWADDR;
         request.header.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK;
-        request.header.nlmsg_seq = REQUEST_ADDRESS_IPV4;
+        request.header.nlmsg_seq = *requests + 1;
 
         ifaddrmsg = NLMSG_DATA(&request.header);
         ifaddrmsg->ifa_family = AF_INET;
@@ -127,9 +120,13 @@ static int add_adresses(int fd, int if_loopback) {
 
         if (sendto_loop(fd, &request, request.header.nlmsg_len, 0, &sa.sa, sizeof(sa)) < 0)
                 return -errno;
+        (*requests)++;
+
+        if (!socket_ipv6_is_supported())
+                return 0;
 
         request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-        request.header.nlmsg_seq = REQUEST_ADDRESS_IPV6;
+        request.header.nlmsg_seq = *requests + 1;
 
         ifaddrmsg->ifa_family = AF_INET6;
         ifaddrmsg->ifa_prefixlen = 128;
@@ -139,11 +136,12 @@ static int add_adresses(int fd, int if_loopback) {
 
         if (sendto_loop(fd, &request, request.header.nlmsg_len, 0, &sa.sa, sizeof(sa)) < 0)
                 return -errno;
+        (*requests)++;
 
         return 0;
 }
 
-static int start_interface(int fd, int if_loopback) {
+static int start_interface(int fd, int if_loopback, unsigned *requests) {
         union {
                 struct sockaddr sa;
                 struct sockaddr_nl nl;
@@ -161,7 +159,7 @@ static int start_interface(int fd, int if_loopback) {
         request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
         request.header.nlmsg_type = RTM_NEWLINK;
         request.header.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
-        request.header.nlmsg_seq = REQUEST_FLAGS;
+        request.header.nlmsg_seq = *requests + 1;
 
         ifinfomsg = NLMSG_DATA(&request.header);
         ifinfomsg->ifi_family = AF_UNSPEC;
@@ -175,10 +173,12 @@ static int start_interface(int fd, int if_loopback) {
         if (sendto_loop(fd, &request, request.header.nlmsg_len, 0, &sa.sa, sizeof(sa)) < 0)
                 return -errno;
 
+        (*requests)++;
+
         return 0;
 }
 
-static int read_response(int fd) {
+static int read_response(int fd, unsigned requests_max) {
         union {
                 struct sockaddr sa;
                 struct sockaddr_nl nl;
@@ -208,7 +208,7 @@ static int read_response(int fd) {
 
         if (response.header.nlmsg_type != NLMSG_ERROR ||
             (pid_t) response.header.nlmsg_pid != getpid() ||
-            response.header.nlmsg_seq >= REQUEST_ALL)
+            response.header.nlmsg_seq >= requests_max)
                 return 0;
 
         if ((size_t) l < NLMSG_LENGTH(sizeof(struct nlmsgerr)) ||
@@ -217,8 +217,10 @@ static int read_response(int fd) {
 
         nlmsgerr = NLMSG_DATA(&response.header);
 
-        if (nlmsgerr->error < 0 && nlmsgerr->error != -EEXIST)
+        if (nlmsgerr->error < 0 && nlmsgerr->error != -EEXIST) {
+                log_warning("Netlink failure for request %i: %s", response.header.nlmsg_seq, strerror(-nlmsgerr->error));
                 return nlmsgerr->error;
+        }
 
         return response.header.nlmsg_seq;
 }
@@ -230,8 +232,7 @@ int loopback_setup(void) {
                 struct sockaddr_nl nl;
                 struct sockaddr_storage storage;
         } sa;
-        int requests = REQUEST_NONE;
-
+        unsigned requests = 0, i;
         int fd;
 
         errno = 0;
@@ -249,25 +250,22 @@ int loopback_setup(void) {
                 goto finish;
         }
 
-        if ((r = add_adresses(fd, if_loopback)) < 0)
+        if ((r = add_adresses(fd, if_loopback, &requests)) < 0)
                 goto finish;
 
-        if ((r = start_interface(fd, if_loopback)) < 0)
+        if ((r = start_interface(fd, if_loopback, &requests)) < 0)
                 goto finish;
 
-        do {
-                if ((r = read_response(fd)) < 0)
+        for (i = 0; i < requests; i++) {
+                if ((r = read_response(fd, requests)) < 0)
                         goto finish;
-
-                requests |= r;
-
-        } while (requests != REQUEST_ALL);
+        }
 
         r = 0;
 
 finish:
         if (r < 0)
-                log_error("Failed to configure loopback device: %s", strerror(-r));
+                log_warning("Failed to configure loopback device: %s", strerror(-r));
 
         if (fd >= 0)
                 close_nointr_nofail(fd);