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"
34 static int start_loopback_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
35 struct state
*s
= userdata
;
38 assert(s
->n_messages
> 0);
42 log_debug_errno(sd_netlink_message_get_errno(m
), "Got start error code: %m");
44 s
->rcode
= sd_netlink_message_get_errno(m
);
49 static int start_loopback(sd_netlink
*rtnl
, struct state
*s
) {
50 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
56 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_SETLINK
, LOOPBACK_IFINDEX
);
60 r
= sd_rtnl_message_link_set_flags(req
, IFF_UP
, IFF_UP
);
64 r
= sd_netlink_call_async(rtnl
, req
, start_loopback_handler
, s
, USEC_INFINITY
, NULL
);
72 static int generic_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
73 struct state
*s
= userdata
;
76 assert(s
->n_messages
> 0);
79 /* Note that we don't really care whether the addresses could be added or not */
81 log_debug_errno(sd_netlink_message_get_errno(m
), "Got address error code: %m");
86 static int add_ipv4_address(sd_netlink
*rtnl
, struct state
*s
) {
87 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
93 r
= sd_rtnl_message_new_addr(rtnl
, &req
, RTM_NEWADDR
, LOOPBACK_IFINDEX
, AF_INET
);
97 r
= sd_rtnl_message_addr_set_prefixlen(req
, 8);
101 r
= sd_rtnl_message_addr_set_flags(req
, IFA_F_PERMANENT
);
105 r
= sd_rtnl_message_addr_set_scope(req
, RT_SCOPE_HOST
);
109 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &(struct in_addr
) { .s_addr
= htobe32(INADDR_LOOPBACK
) } );
113 r
= sd_netlink_call_async(rtnl
, req
, generic_handler
, s
, USEC_INFINITY
, NULL
);
121 static int add_ipv6_address(sd_netlink
*rtnl
, struct state
*s
) {
122 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
128 r
= sd_rtnl_message_new_addr(rtnl
, &req
, RTM_NEWADDR
, LOOPBACK_IFINDEX
, AF_INET6
);
132 r
= sd_rtnl_message_addr_set_prefixlen(req
, 128);
136 r
= sd_rtnl_message_addr_set_flags(req
, IFA_F_PERMANENT
);
140 r
= sd_rtnl_message_addr_set_scope(req
, RT_SCOPE_HOST
);
144 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &in6addr_loopback
);
148 r
= sd_netlink_call_async(rtnl
, req
, generic_handler
, s
, USEC_INFINITY
, NULL
);
156 static bool check_loopback(sd_netlink
*rtnl
) {
157 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
161 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_GETLINK
, LOOPBACK_IFINDEX
);
165 r
= sd_netlink_call(rtnl
, req
, USEC_INFINITY
, &reply
);
169 r
= sd_rtnl_message_link_get_flags(reply
, &flags
);
173 return flags
& IFF_UP
;
176 int loopback_setup(void) {
177 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
178 struct state state
= {};
181 r
= sd_netlink_open(&rtnl
);
183 return log_error_errno(r
, "Failed to open netlink: %m");
185 /* Note that we add the IP addresses here explicitly even though the kernel does that too implicitly when
186 * setting up the loopback device. The reason we do this here a second time (and possibly race against the
187 * kernel) is that we want to synchronously wait until the IP addresses are set up correctly, see
189 * https://github.com/systemd/systemd/issues/5641 */
191 r
= add_ipv4_address(rtnl
, &state
);
193 return log_error_errno(r
, "Failed to enqueue IPv4 loopback address add request: %m");
195 r
= add_ipv6_address(rtnl
, &state
);
197 return log_error_errno(r
, "Failed to enqueue IPv4 loopback address add request: %m");
199 r
= start_loopback(rtnl
, &state
);
201 return log_error_errno(r
, "Failed to enqueue loopback interface start request: %m");
203 while (state
.n_messages
> 0) {
204 r
= sd_netlink_wait(rtnl
, USEC_INFINITY
);
206 return log_error_errno(r
, "Failed to wait for netlink event: %m");
208 r
= sd_netlink_process(rtnl
, NULL
);
210 return log_warning_errno(r
, "Failed to process netlink event: %m");
213 if (state
.rcode
!= 0) {
215 /* If we lack the permissions to configure the
216 * loopback device, but we find it to be already
217 * configured, let's exit cleanly, in order to
218 * supported unprivileged containers. */
219 if (state
.rcode
== -EPERM
&& check_loopback(rtnl
))
222 return log_warning_errno(state
.rcode
, "Failed to configure loopback device: %m");