2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "sd-netlink.h"
25 #include "loopback-setup.h"
27 #include "netlink-util.h"
29 #define LOOPBACK_SETUP_TIMEOUT_USEC (5 * USEC_PER_SEC)
37 static int generic_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
38 struct state
*s
= userdata
;
41 assert(s
->n_messages
> 0);
45 log_debug_errno(sd_netlink_message_get_errno(m
), "Failed to %s: %m", s
->title
);
47 s
->rcode
= sd_netlink_message_get_errno(m
);
52 static int start_loopback(sd_netlink
*rtnl
, struct state
*s
) {
53 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
59 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_SETLINK
, LOOPBACK_IFINDEX
);
63 r
= sd_rtnl_message_link_set_flags(req
, IFF_UP
, IFF_UP
);
67 r
= sd_netlink_call_async(rtnl
, req
, generic_handler
, s
, LOOPBACK_SETUP_TIMEOUT_USEC
, NULL
);
75 static int add_ipv4_address(sd_netlink
*rtnl
, struct state
*s
) {
76 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
82 r
= sd_rtnl_message_new_addr(rtnl
, &req
, RTM_NEWADDR
, LOOPBACK_IFINDEX
, AF_INET
);
86 r
= sd_rtnl_message_addr_set_prefixlen(req
, 8);
90 r
= sd_rtnl_message_addr_set_flags(req
, IFA_F_PERMANENT
);
94 r
= sd_rtnl_message_addr_set_scope(req
, RT_SCOPE_HOST
);
98 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &(struct in_addr
) { .s_addr
= htobe32(INADDR_LOOPBACK
) } );
102 r
= sd_netlink_call_async(rtnl
, req
, generic_handler
, s
, USEC_INFINITY
, NULL
);
110 static int add_ipv6_address(sd_netlink
*rtnl
, struct state
*s
) {
111 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
117 r
= sd_rtnl_message_new_addr(rtnl
, &req
, RTM_NEWADDR
, LOOPBACK_IFINDEX
, AF_INET6
);
121 r
= sd_rtnl_message_addr_set_prefixlen(req
, 128);
125 r
= sd_rtnl_message_addr_set_flags(req
, IFA_F_PERMANENT
);
129 r
= sd_rtnl_message_addr_set_scope(req
, RT_SCOPE_HOST
);
133 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &in6addr_loopback
);
137 r
= sd_netlink_call_async(rtnl
, req
, generic_handler
, s
, USEC_INFINITY
, NULL
);
145 static bool check_loopback(sd_netlink
*rtnl
) {
146 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
150 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_GETLINK
, LOOPBACK_IFINDEX
);
154 r
= sd_netlink_call(rtnl
, req
, USEC_INFINITY
, &reply
);
158 r
= sd_rtnl_message_link_get_flags(reply
, &flags
);
162 return flags
& IFF_UP
;
165 int loopback_setup(void) {
166 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
167 struct state state_4
= { .title
= "add address 127.0.0.1 to loopback interface" },
168 state_6
= { .title
= "add address ::1 to loopback interface"},
169 state_up
= { .title
= "bring loopback interface up" };
172 r
= sd_netlink_open(&rtnl
);
174 return log_error_errno(r
, "Failed to open netlink: %m");
176 /* Note that we add the IP addresses here explicitly even though the kernel does that too implicitly when
177 * setting up the loopback device. The reason we do this here a second time (and possibly race against the
178 * kernel) is that we want to synchronously wait until the IP addresses are set up correctly, see
180 * https://github.com/systemd/systemd/issues/5641 */
182 r
= add_ipv4_address(rtnl
, &state_4
);
184 return log_error_errno(r
, "Failed to enqueue IPv4 loopback address add request: %m");
186 r
= add_ipv6_address(rtnl
, &state_6
);
188 return log_error_errno(r
, "Failed to enqueue IPv6 loopback address add request: %m");
190 r
= start_loopback(rtnl
, &state_up
);
192 return log_error_errno(r
, "Failed to enqueue loopback interface start request: %m");
194 while (state_4
.n_messages
+ state_6
.n_messages
+ state_up
.n_messages
> 0) {
195 r
= sd_netlink_wait(rtnl
, LOOPBACK_SETUP_TIMEOUT_USEC
);
197 return log_error_errno(r
, "Failed to wait for netlink event: %m");
199 r
= sd_netlink_process(rtnl
, NULL
);
201 return log_warning_errno(r
, "Failed to process netlink event: %m");
204 /* Note that we don't really care whether the addresses could be added or not */
205 if (state_up
.rcode
!= 0) {
206 /* If we lack the permissions to configure the loopback device,
207 * but we find it to be already configured, let's exit cleanly,
208 * in order to supported unprivileged containers. */
209 if (state_up
.rcode
== -EPERM
&& check_loopback(rtnl
))
212 return log_warning_errno(state_up
.rcode
, "Failed to configure loopback device: %m");