chiark / gitweb /
networkd: correct logging message
[elogind.git] / src / network / networkd-link.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 <netinet/ether.h>
23 #include <linux/if.h>
24
25 #include "networkd.h"
26 #include "libudev-private.h"
27 #include "util.h"
28
29 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
30         _cleanup_link_free_ Link *link = NULL;
31         const char *mac;
32         struct ether_addr *mac_addr;
33         const char *ifname;
34         int r;
35
36         assert(device);
37         assert(ret);
38
39         link = new0(Link, 1);
40         if (!link)
41                 return -ENOMEM;
42
43         link->manager = manager;
44         link->state = _LINK_STATE_INVALID;
45
46         link->ifindex = udev_device_get_ifindex(device);
47         if (link->ifindex <= 0)
48                 return -EINVAL;
49
50         mac = udev_device_get_sysattr_value(device, "address");
51         if (mac) {
52                 mac_addr = ether_aton(mac);
53                 if (mac_addr)
54                         memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
55         }
56
57         ifname = udev_device_get_sysname(device);
58         link->ifname = strdup(ifname);
59
60         r = hashmap_put(manager->links, &link->ifindex, link);
61         if (r < 0)
62                 return r;
63
64         *ret = link;
65         link = NULL;
66
67         return 0;
68 }
69
70 void link_free(Link *link) {
71         if (!link)
72                 return;
73
74         assert(link->manager);
75
76         hashmap_remove(link->manager->links, &link->ifindex);
77
78         free(link->ifname);
79
80         free(link);
81 }
82
83 int link_add(Manager *m, struct udev_device *device) {
84         Link *link;
85         Network *network;
86         int r;
87         uint64_t ifindex;
88         const char *devtype;
89
90         assert(m);
91         assert(device);
92
93         ifindex = udev_device_get_ifindex(device);
94         link = hashmap_get(m->links, &ifindex);
95         if (link)
96                 return 0;
97
98         r = link_new(m, device, &link);
99         if (r < 0) {
100                 log_error("Could not create link: %s", strerror(-r));
101                 return r;
102         }
103
104         devtype = udev_device_get_devtype(device);
105         if (streq_ptr(devtype, "bridge")) {
106                 r = bridge_set_link(m, link);
107                 if (r < 0)
108                         return r == -ENOENT ? 0 : r;
109         }
110
111         r = network_get(m, device, &network);
112         if (r < 0)
113                 return r == -ENOENT ? 0 : r;
114
115         r = network_apply(m, network, link);
116         if (r < 0)
117                 return r;
118
119         return 0;
120 }
121
122 static int link_enter_configured(Link *link) {
123         log_info("Link '%s' configured", link->ifname);
124
125         link->state = LINK_STATE_CONFIGURED;
126
127         return 0;
128 }
129
130 static int link_enter_failed(Link *link) {
131         link->state = LINK_STATE_FAILED;
132
133         return 0;
134 }
135
136 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
137         Link *link = userdata;
138         int r;
139
140         assert(link->rtnl_messages > 0);
141         assert(link->state == LINK_STATE_SET_ROUTES || link->state == LINK_STATE_FAILED);
142
143         link->rtnl_messages --;
144
145         if (link->state == LINK_STATE_FAILED)
146                 return 1;
147
148         r = sd_rtnl_message_get_errno(m);
149         if (r < 0 && r != -EEXIST)
150                 log_warning("Could not set route on interface '%s': %s",
151                             link->ifname, strerror(-r));
152
153         if (link->rtnl_messages == 0) {
154                 log_info("Routes set for link '%s'", link->ifname);
155                 link_enter_configured(link);
156         }
157
158         return 1;
159 }
160
161 static int link_enter_set_routes(Link *link) {
162         Route *route;
163         int r;
164
165         assert(link);
166         assert(link->network);
167         assert(link->rtnl_messages == 0);
168         assert(link->state == LINK_STATE_ADDRESSES_SET);
169
170         link->state = LINK_STATE_SET_ROUTES;
171
172         if (!link->network->routes)
173                 return link_enter_configured(link);
174
175         LIST_FOREACH(routes, route, link->network->routes) {
176                 r = route_configure(route, link, &route_handler);
177                 if (r < 0) {
178                         log_warning("Could not set routes for link '%s'", link->ifname);
179                         return link_enter_failed(link);
180                 }
181
182                 link->rtnl_messages ++;
183         }
184
185         return 0;
186 }
187
188 static int link_enter_addresses_set(Link *link) {
189         link->state = LINK_STATE_ADDRESSES_SET;
190
191         return link_enter_set_routes(link);
192 }
193
194 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
195         Link *link = userdata;
196         int r;
197
198         assert(link->rtnl_messages > 0);
199         assert(link->state == LINK_STATE_SET_ADDRESSES || link->state == LINK_STATE_FAILED);
200
201         link->rtnl_messages --;
202
203         if (link->state == LINK_STATE_FAILED)
204                 return 1;
205
206         r = sd_rtnl_message_get_errno(m);
207         if (r < 0 && r != -EEXIST)
208                 log_warning("Could not set address on interface '%s': %s",
209                             link->ifname, strerror(-r));
210
211         if (link->rtnl_messages == 0) {
212                 log_info("Addresses set for link '%s'", link->ifname);
213                 link_enter_addresses_set(link);
214         }
215
216         return 1;
217 }
218
219 static int link_enter_set_addresses(Link *link) {
220         Address *address;
221         int r;
222
223         assert(link);
224         assert(link->network);
225         assert(link->rtnl_messages == 0);
226
227         if (!link->network->addresses)
228                 return link_enter_addresses_set(link);
229
230         link->state = LINK_STATE_SET_ADDRESSES;
231
232         LIST_FOREACH(addresses, address, link->network->addresses) {
233                 r = address_configure(address, link, &address_handler);
234                 if (r < 0) {
235                         log_warning("Could not set addresses for link '%s'", link->ifname);
236                         return link_enter_failed(link);
237                 }
238
239                 link->rtnl_messages ++;
240         }
241
242         return 0;
243 }
244
245 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
246         Link *link = userdata;
247         int r;
248
249         r = sd_rtnl_message_get_errno(m);
250         if (r < 0) {
251                 log_warning("Could not get state of interface '%s': %s",
252                             link->ifname, strerror(-r));
253                 link_enter_failed(link);
254         }
255
256         return 1;
257 }
258
259 static int link_get(Link *link) {
260         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
261         int r;
262
263         assert(link);
264         assert(link->manager);
265         assert(link->manager->rtnl);
266
267         r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
268         if (r < 0) {
269                 log_error("Could not allocate RTM_GETLINK message");
270                 return r;
271         }
272
273         r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
274         if (r < 0) {
275                 log_error("Could not send rtnetlink message: %s", strerror(-r));
276                 return r;
277         }
278
279         return 0;
280 }
281
282 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
283         Link *link = userdata;
284         int r;
285
286         r = sd_rtnl_message_get_errno(m);
287         if (r < 0) {
288                 log_warning("Could not bring up interface '%s': %s",
289                             link->ifname, strerror(-r));
290                 link_enter_failed(link);
291         }
292
293         return 1;
294 }
295
296 static int link_up(Link *link) {
297         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
298         int r;
299
300         assert(link);
301         assert(link->manager);
302         assert(link->manager->rtnl);
303
304         r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
305         if (r < 0) {
306                 log_error("Could not allocate RTM_SETLINK message");
307                 return r;
308         }
309
310         r = sd_rtnl_message_link_set_flags(req, IFF_UP);
311         if (r < 0) {
312                 log_error("Could not set link flags");
313                 return r;
314         }
315
316         r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
317         if (r < 0) {
318                 log_error("Could not send rtnetlink message: %s", strerror(-r));
319                 return r;
320         }
321
322         return 0;
323 }
324
325 static int link_enter_bridge_joined(Link *link) {
326         int r;
327
328         link->state = LINK_STATE_BRIDGE_JOINED;
329
330         r = link_up(link);
331         if (r < 0)
332                 return link_enter_failed(link);
333
334         return link_enter_set_addresses(link);
335 }
336
337 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
338         Link *link = userdata;
339         int r;
340
341         assert(link->state == LINK_STATE_JOIN_BRIDGE || link->state == LINK_STATE_FAILED);
342
343         if (link->state == LINK_STATE_FAILED)
344                 return 1;
345
346         r = sd_rtnl_message_get_errno(m);
347         if (r < 0)
348                 log_warning("Could not join interface '%s' to bridge '%s': %s",
349                             link->ifname, link->network->bridge->name, strerror(-r));
350         else
351                 log_info("Join interface '%s' to bridge: %s",
352                             link->ifname, link->network->bridge->name);
353
354         link_enter_bridge_joined(link);
355
356         return 1;
357 }
358
359 static int link_enter_join_bridge(Link *link) {
360         int r;
361
362         assert(link);
363         assert(link->network);
364
365         if (!link->network->bridge)
366                 return link_enter_bridge_joined(link);
367
368         link->state = LINK_STATE_JOIN_BRIDGE;
369
370         r = bridge_join(link->network->bridge, link, &bridge_handler);
371         if (r < 0) {
372                 log_warning("Could not join link '%s' to bridge '%s'", link->ifname,
373                             link->network->bridge->name);
374                 return link_enter_failed(link);
375         }
376
377         return 0;
378 }
379
380 int link_configure(Link *link) {
381         int r;
382
383         r = link_get(link);
384         if (r < 0)
385                 return link_enter_failed(link);
386
387         r = link_enter_join_bridge(link);
388         if (r < 0)
389                 return link_enter_failed(link);
390
391         return 0;
392 }
393
394 int link_update_flags(Link *link, unsigned flags) {
395         assert(link);
396
397         if (link->flags & IFF_UP && !(flags & IFF_UP))
398                 log_info("Interface '%s' is down", link->ifname);
399         else if (!(link->flags & IFF_UP) && flags & IFF_UP)
400                 log_info("Interface '%s' is up", link->ifname);
401
402         if (link->flags & IFF_LOWER_UP && !(flags & IFF_LOWER_UP))
403                 log_info("Interface '%s' is disconnected", link->ifname);
404         else if (!(link->flags & IFF_LOWER_UP) && flags & IFF_LOWER_UP)
405                 log_info("Interface '%s' is connected", link->ifname);
406
407         link->flags = flags;
408
409         return 0;
410 }