chiark / gitweb /
networkd: split out networkd-link.h
[elogind.git] / src / network / networkd-netdev.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 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   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <net/if.h>
23
24 #include "networkd-netdev.h"
25 #include "networkd-link.h"
26 #include "network-internal.h"
27 #include "path-util.h"
28 #include "conf-files.h"
29 #include "conf-parser.h"
30 #include "list.h"
31 #include "siphash24.h"
32
33 const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
34         [NETDEV_KIND_BRIDGE] = &bridge_vtable,
35         [NETDEV_KIND_BOND] = &bond_vtable,
36         [NETDEV_KIND_VLAN] = &vlan_vtable,
37         [NETDEV_KIND_MACVLAN] = &macvlan_vtable,
38         [NETDEV_KIND_VXLAN] = &vxlan_vtable,
39         [NETDEV_KIND_IPIP] = &ipip_vtable,
40         [NETDEV_KIND_GRE] = &gre_vtable,
41         [NETDEV_KIND_SIT] = &sit_vtable,
42         [NETDEV_KIND_VTI] = &vti_vtable,
43         [NETDEV_KIND_VETH] = &veth_vtable,
44         [NETDEV_KIND_DUMMY] = &dummy_vtable,
45         [NETDEV_KIND_TUN] = &tun_vtable,
46         [NETDEV_KIND_TAP] = &tap_vtable,
47 };
48
49 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
50         [NETDEV_KIND_BRIDGE] = "bridge",
51         [NETDEV_KIND_BOND] = "bond",
52         [NETDEV_KIND_VLAN] = "vlan",
53         [NETDEV_KIND_MACVLAN] = "macvlan",
54         [NETDEV_KIND_VXLAN] = "vxlan",
55         [NETDEV_KIND_IPIP] = "ipip",
56         [NETDEV_KIND_GRE] = "gre",
57         [NETDEV_KIND_SIT] = "sit",
58         [NETDEV_KIND_VETH] = "veth",
59         [NETDEV_KIND_VTI] = "vti",
60         [NETDEV_KIND_DUMMY] = "dummy",
61         [NETDEV_KIND_TUN] = "tun",
62         [NETDEV_KIND_TAP] = "tap",
63 };
64
65 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
66 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
67
68
69 static void netdev_cancel_callbacks(NetDev *netdev) {
70         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
71         netdev_join_callback *callback;
72
73         if (!netdev)
74                 return;
75
76         rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
77
78         while ((callback = netdev->callbacks)) {
79                 if (m) {
80                         assert(callback->link);
81                         assert(callback->callback);
82                         assert(netdev->manager);
83                         assert(netdev->manager->rtnl);
84
85                         callback->callback(netdev->manager->rtnl, m, link);
86                 }
87
88                 LIST_REMOVE(callbacks, netdev->callbacks, callback);
89                 free(callback);
90         }
91 }
92
93 static void netdev_free(NetDev *netdev) {
94         if (!netdev)
95                 return;
96
97         netdev_cancel_callbacks(netdev);
98
99         if (netdev->ifname)
100                 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
101
102         free(netdev->filename);
103
104         free(netdev->description);
105         free(netdev->ifname);
106         free(netdev->mac);
107
108         condition_free_list(netdev->match_host);
109         condition_free_list(netdev->match_virt);
110         condition_free_list(netdev->match_kernel);
111         condition_free_list(netdev->match_arch);
112
113         if (NETDEV_VTABLE(netdev) &&
114             NETDEV_VTABLE(netdev)->done)
115                 NETDEV_VTABLE(netdev)->done(netdev);
116
117         free(netdev);
118 }
119
120 NetDev *netdev_unref(NetDev *netdev) {
121         if (netdev && (-- netdev->n_ref <= 0))
122                 netdev_free(netdev);
123
124         return NULL;
125 }
126
127 NetDev *netdev_ref(NetDev *netdev) {
128         if (netdev)
129                 assert_se(++ netdev->n_ref >= 2);
130
131         return netdev;
132 }
133
134 void netdev_drop(NetDev *netdev) {
135         if (!netdev || netdev->state == NETDEV_STATE_LINGER)
136                 return;
137
138         netdev->state = NETDEV_STATE_LINGER;
139
140         log_debug_netdev(netdev, "netdev removed");
141
142         netdev_cancel_callbacks(netdev);
143
144         netdev_unref(netdev);
145
146         return;
147 }
148
149 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
150         NetDev *netdev;
151
152         assert(manager);
153         assert(name);
154         assert(ret);
155
156         netdev = hashmap_get(manager->netdevs, name);
157         if (!netdev) {
158                 *ret = NULL;
159                 return -ENOENT;
160         }
161
162         *ret = netdev;
163
164         return 0;
165 }
166
167 static int netdev_enter_failed(NetDev *netdev) {
168         netdev->state = NETDEV_STATE_FAILED;
169
170         return 0;
171 }
172
173 static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_handler_t callback) {
174         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
175         int r;
176
177         assert(netdev);
178         assert(netdev->state == NETDEV_STATE_READY);
179         assert(netdev->manager);
180         assert(netdev->manager->rtnl);
181         assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
182         assert(link);
183         assert(callback);
184
185         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
186                                      RTM_SETLINK, link->ifindex);
187         if (r < 0) {
188                 log_error_netdev(netdev,
189                                  "Could not allocate RTM_SETLINK message: %s",
190                                  strerror(-r));
191                 return r;
192         }
193
194         r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
195         if (r < 0) {
196                 log_error_netdev(netdev,
197                                  "Could not append IFLA_MASTER attribute: %s",
198                                  strerror(-r));
199                 return r;
200         }
201
202         r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
203         if (r < 0) {
204                 log_error_netdev(netdev,
205                                  "Could not send rtnetlink message: %s",
206                                  strerror(-r));
207                 return r;
208         }
209
210         link_ref(link);
211
212         log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
213
214         return 0;
215 }
216
217 static int netdev_enter_ready(NetDev *netdev) {
218         netdev_join_callback *callback, *callback_next;
219         int r;
220
221         assert(netdev);
222         assert(netdev->ifname);
223
224         if (netdev->state != NETDEV_STATE_CREATING)
225                 return 0;
226
227         netdev->state = NETDEV_STATE_READY;
228
229         log_info_netdev(netdev, "netdev ready");
230
231         LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) {
232                 /* enslave the links that were attempted to be enslaved before the
233                  * link was ready */
234                 r = netdev_enslave_ready(netdev, callback->link, callback->callback);
235                 if (r < 0)
236                         return r;
237
238                 LIST_REMOVE(callbacks, netdev->callbacks, callback);
239                 link_unref(callback->link);
240                 free(callback);
241         }
242
243         return 0;
244 }
245
246 /* callback for netdev's created without a backing Link */
247 static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
248         _cleanup_netdev_unref_ NetDev *netdev = userdata;
249         int r;
250
251         assert(netdev->state != _NETDEV_STATE_INVALID);
252
253         r = sd_rtnl_message_get_errno(m);
254         if (r == -EEXIST)
255                 log_debug_netdev(netdev, "netdev exists, using existing");
256         else if (r < 0) {
257                 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
258                 netdev_drop(netdev);
259
260                 return 1;
261         }
262
263         log_debug_netdev(netdev, "created");
264
265         return 1;
266 }
267
268 int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
269         int r;
270
271         assert(netdev);
272         assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
273
274         if (netdev->state == NETDEV_STATE_READY) {
275                 r = netdev_enslave_ready(netdev, link, callback);
276                 if (r < 0)
277                         return r;
278         } else {
279                 /* the netdev is not yet read, save this request for when it is*/
280                 netdev_join_callback *cb;
281
282                 cb = new0(netdev_join_callback, 1);
283                 if (!cb)
284                         return log_oom();
285
286                 cb->callback = callback;
287                 cb->link = link;
288                 link_ref(link);
289
290                 LIST_PREPEND(callbacks, netdev->callbacks, cb);
291
292                 log_debug_netdev(netdev, "will enslave '%s', when reday",
293                                  link->ifname);
294         }
295
296         return 0;
297 }
298
299 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
300         uint16_t type;
301         const char *kind;
302         const char *received_kind;
303         const char *received_name;
304         int r, ifindex;
305
306         assert(netdev);
307         assert(message);
308
309         r = sd_rtnl_message_get_type(message, &type);
310         if (r < 0) {
311                 log_error_netdev(netdev, "Could not get rtnl message type");
312                 return r;
313         }
314
315         if (type != RTM_NEWLINK) {
316                 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
317                 return -EINVAL;
318         }
319
320         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
321         if (r < 0) {
322                 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
323                 netdev_enter_failed(netdev);
324                 return r;
325         } else if (ifindex <= 0) {
326                 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
327                 netdev_enter_failed(netdev);
328                 return r;
329         }
330
331         if (netdev->ifindex > 0) {
332                 if (netdev->ifindex != ifindex) {
333                         log_error_netdev(netdev, "Could not set ifindex to %d, already set to %d",
334                                          ifindex, netdev->ifindex);
335                         netdev_enter_failed(netdev);
336                         return -EEXIST;
337                 } else
338                         /* ifindex already set to the same for this netdev */
339                         return 0;
340         }
341
342         r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
343         if (r < 0) {
344                 log_error_netdev(netdev, "Could not get IFNAME");
345                 return r;
346         }
347
348         if (!streq(netdev->ifname, received_name)) {
349                 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
350                                  received_name);
351                 netdev_enter_failed(netdev);
352                 return r;
353         }
354
355         r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
356         if (r < 0) {
357                 log_error_netdev(netdev, "Could not get LINKINFO");
358                 return r;
359         }
360
361         r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
362         if (r < 0) {
363                 log_error_netdev(netdev, "Could not get KIND");
364                 return r;
365         }
366
367         r = sd_rtnl_message_exit_container(message);
368         if (r < 0) {
369                 log_error_netdev(netdev, "Could not exit container");
370                 return r;
371         }
372
373         if (netdev->kind == NETDEV_KIND_TAP)
374                 /* the kernel does not distinguish between tun and tap */
375                 kind = "tun";
376         else {
377                 kind = netdev_kind_to_string(netdev->kind);
378                 if (!kind) {
379                         log_error_netdev(netdev, "Could not get kind");
380                         netdev_enter_failed(netdev);
381                         return -EINVAL;
382                 }
383         }
384
385         if (!streq(kind, received_kind)) {
386                 log_error_netdev(netdev,
387                                  "Received newlink with wrong KIND %s, "
388                                  "expected %s", received_kind, kind);
389                 netdev_enter_failed(netdev);
390                 return r;
391         }
392
393         netdev->ifindex = ifindex;
394
395         log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
396
397         netdev_enter_ready(netdev);
398
399         return 0;
400 }
401
402 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
403
404 int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
405         _cleanup_free_ struct ether_addr *mac = NULL;
406         uint8_t result[8];
407         size_t l, sz;
408         uint8_t *v;
409         int r;
410
411         assert(ifname);
412         assert(ret);
413
414         mac = new0(struct ether_addr, 1);
415         if (!mac)
416                 return -ENOMEM;
417
418         l = strlen(ifname);
419         sz = sizeof(sd_id128_t) + l;
420         v = alloca(sz);
421
422         /* fetch some persistent data unique to the machine */
423         r = sd_id128_get_machine((sd_id128_t*) v);
424         if (r < 0)
425                 return r;
426
427         /* combine with some data unique (on this machine) to this
428          * netdev */
429         memcpy(v + sizeof(sd_id128_t), ifname, l);
430
431         /* Let's hash the host machine ID plus the container name. We
432          * use a fixed, but originally randomly created hash key here. */
433         siphash24(result, v, sz, HASH_KEY.bytes);
434
435         assert_cc(ETH_ALEN <= sizeof(result));
436         memcpy(mac->ether_addr_octet, result, ETH_ALEN);
437
438         /* see eth_random_addr in the kernel */
439         mac->ether_addr_octet[0] &= 0xfe;        /* clear multicast bit */
440         mac->ether_addr_octet[0] |= 0x02;        /* set local assignment bit (IEEE802) */
441
442         *ret = mac;
443         mac = NULL;
444
445         return 0;
446 }
447
448 static int netdev_create(NetDev *netdev, Link *link) {
449         int r;
450
451         assert(netdev);
452
453         /* create netdev */
454         if (NETDEV_VTABLE(netdev)->create) {
455                 r = NETDEV_VTABLE(netdev)->create(netdev);
456                 if (r < 0)
457                         return r;
458
459                 log_debug_netdev(netdev, "created");
460         } else {
461                 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
462
463                 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
464                 if (r < 0) {
465                         log_error_netdev(netdev,
466                                          "Could not allocate RTM_NEWLINK message: %s",
467                                          strerror(-r));
468                         return r;
469                 }
470
471                 r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
472                 if (r < 0) {
473                         log_error_netdev(netdev,
474                                          "Could not append IFLA_IFNAME, attribute: %s",
475                                          strerror(-r));
476                         return r;
477                 }
478
479                 if (netdev->mac) {
480                         r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
481                         if (r < 0) {
482                                 log_error_netdev(netdev,
483                                                  "Could not append IFLA_ADDRESS attribute: %s",
484                                                  strerror(-r));
485                             return r;
486                         }
487                 }
488
489                 if (netdev->mtu) {
490                         r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
491                         if (r < 0) {
492                                 log_error_netdev(netdev,
493                                                  "Could not append IFLA_MTU attribute: %s",
494                                                  strerror(-r));
495                                 return r;
496                         }
497                 }
498
499                 if (link) {
500                         r = sd_rtnl_message_append_u32(m, IFLA_LINK, link->ifindex);
501                         if (r < 0) {
502                                 log_error_netdev(netdev,
503                                                  "Colud not append IFLA_LINK attribute: %s",
504                                                  strerror(-r));
505                                 return r;
506                         }
507                 }
508
509                 r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
510                 if (r < 0) {
511                         log_error_netdev(netdev,
512                                          "Could not append IFLA_LINKINFO attribute: %s",
513                                          strerror(-r));
514                         return r;
515                 }
516
517                 r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
518                                                          netdev_kind_to_string(netdev->kind));
519                 if (r < 0) {
520                         log_error_netdev(netdev,
521                                          "Could not append IFLA_INFO_DATA attribute: %s",
522                                          strerror(-r));
523                         return r;
524                 }
525
526                 if (NETDEV_VTABLE(netdev)->fill_message_create) {
527                         r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m);
528                         if (r < 0)
529                                 return r;
530                 }
531
532                 r = sd_rtnl_message_close_container(m);
533                 if (r < 0) {
534                         log_error_netdev(netdev,
535                                          "Could not append IFLA_LINKINFO attribute: %s",
536                                          strerror(-r));
537                         return r;
538                 }
539
540                 r = sd_rtnl_message_close_container(m);
541                 if (r < 0) {
542                         log_error_netdev(netdev,
543                                          "Could not append IFLA_LINKINFO attribute: %s",
544                                          strerror(-r));
545                         return r;
546                 }
547
548
549                 r = sd_rtnl_call_async(netdev->manager->rtnl, m, netdev_create_handler, netdev, 0, NULL);
550                 if (r < 0) {
551                         log_error_netdev(netdev,
552                                          "Could not send rtnetlink message: %s", strerror(-r));
553                         return r;
554                 }
555
556                 netdev_ref(netdev);
557
558                 netdev->state = NETDEV_STATE_CREATING;
559
560                 log_debug_netdev(netdev, "creating");
561         }
562
563         return 0;
564 }
565
566 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
567 int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
568         int r;
569
570         assert(netdev);
571         assert(netdev->manager);
572         assert(netdev->manager->rtnl);
573         assert(NETDEV_VTABLE(netdev));
574
575         switch (NETDEV_VTABLE(netdev)->create_type) {
576         case NETDEV_CREATE_MASTER:
577                 r = netdev_enslave(netdev, link, callback);
578                 if (r < 0)
579                         return r;
580
581                 break;
582         case NETDEV_CREATE_STACKED:
583                 r = netdev_create(netdev, link);
584                 if (r < 0)
585                         return r;
586
587                 break;
588         default:
589                 assert_not_reached("Can not join independent netdev");
590         }
591
592         return 0;
593 }
594
595 static int netdev_load_one(Manager *manager, const char *filename) {
596         _cleanup_netdev_unref_ NetDev *netdev = NULL;
597         _cleanup_free_ NetDev *netdev_raw = NULL;
598         _cleanup_fclose_ FILE *file = NULL;
599         int r;
600
601         assert(manager);
602         assert(filename);
603
604         file = fopen(filename, "re");
605         if (!file) {
606                 if (errno == ENOENT)
607                         return 0;
608                 else
609                         return -errno;
610         }
611
612         if (null_or_empty_fd(fileno(file))) {
613                 log_debug("Skipping empty file: %s", filename);
614                 return 0;
615         }
616
617         netdev_raw = new0(NetDev, 1);
618         if (!netdev_raw)
619                 return log_oom();
620
621         netdev_raw->kind = _NETDEV_KIND_INVALID;
622
623         r = config_parse(NULL, filename, file,
624                          "Match\0NetDev\0",
625                          config_item_perf_lookup, network_netdev_gperf_lookup,
626                          true, false, true, netdev_raw);
627         if (r < 0)
628                 return r;
629
630         r = fseek(file, 0, SEEK_SET);
631         if (r < 0)
632                 return -errno;
633
634         /* skip out early if configuration does not match the environment */
635         if (net_match_config(NULL, NULL, NULL, NULL, NULL,
636                              netdev_raw->match_host, netdev_raw->match_virt,
637                              netdev_raw->match_kernel, netdev_raw->match_arch,
638                              NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
639                 return 0;
640
641         if (!NETDEV_VTABLE(netdev_raw)) {
642                 log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename);
643                 return 0;
644         }
645
646         if (!netdev_raw->ifname) {
647                 log_warning("NetDev without Name configured in %s. Ignoring", filename);
648                 return 0;
649         }
650
651         netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size);
652         if (!netdev)
653                 return log_oom();
654
655         netdev->n_ref = 1;
656         netdev->manager = manager;
657         netdev->state = _NETDEV_STATE_INVALID;
658         netdev->kind = netdev_raw->kind;
659         netdev->ifname = netdev_raw->ifname;
660
661         if (NETDEV_VTABLE(netdev)->init)
662                 NETDEV_VTABLE(netdev)->init(netdev);
663
664         r = config_parse(NULL, filename, file,
665                          NETDEV_VTABLE(netdev)->sections,
666                          config_item_perf_lookup, network_netdev_gperf_lookup,
667                          false, false, false, netdev);
668         if (r < 0)
669                 return r;
670
671         /* verify configuration */
672         if (NETDEV_VTABLE(netdev)->config_verify) {
673                 r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename);
674                 if (r < 0)
675                         return 0;
676         }
677
678         netdev->filename = strdup(filename);
679         if (!netdev->filename)
680                 return log_oom();
681
682         if (!netdev->mac) {
683                 r = netdev_get_mac(netdev->ifname, &netdev->mac);
684                 if (r < 0) {
685                         log_error("Failed to generate predictable MAC address for %s",
686                                   netdev->ifname);
687                         return r;
688                 }
689         }
690
691         r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
692         if (r < 0)
693                 return r;
694
695         LIST_HEAD_INIT(netdev->callbacks);
696
697         log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
698
699         switch (NETDEV_VTABLE(netdev)->create_type) {
700         case NETDEV_CREATE_MASTER:
701         case NETDEV_CREATE_INDEPENDENT:
702                 r = netdev_create(netdev, NULL);
703                 if (r < 0)
704                         return r;
705
706                 break;
707         default:
708                 break;
709         }
710
711         netdev = NULL;
712
713         return 0;
714 }
715
716 int netdev_load(Manager *manager) {
717         NetDev *netdev;
718         char **files, **f;
719         int r;
720
721         assert(manager);
722
723         while ((netdev = hashmap_first(manager->netdevs)))
724                 netdev_unref(netdev);
725
726         r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
727         if (r < 0) {
728                 log_error("Failed to enumerate netdev files: %s", strerror(-r));
729                 return r;
730         }
731
732         STRV_FOREACH_BACKWARDS(f, files) {
733                 r = netdev_load_one(manager, *f);
734                 if (r < 0)
735                         return r;
736         }
737
738         strv_free(files);
739
740         return 0;
741 }