chiark / gitweb /
machinectl: fix success check when getting pty from within container
[elogind.git] / src / network / networkd-network.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 "networkd.h"
23 #include "net-util.h"
24 #include "path-util.h"
25 #include "conf-files.h"
26 #include "conf-parser.h"
27
28 static int network_load_one(Manager *manager, const char *filename) {
29         _cleanup_network_free_ Network *network = NULL;
30         _cleanup_fclose_ FILE *file = NULL;
31         int r;
32
33         assert(manager);
34         assert(filename);
35
36         file = fopen(filename, "re");
37         if (!file) {
38                 if (errno == ENOENT)
39                         return 0;
40                 else
41                         return errno;
42         }
43
44         network = new0(Network, 1);
45         if (!network)
46                 return log_oom();
47
48         network->manager = manager;
49
50         LIST_HEAD_INIT(network->addresses);
51         LIST_HEAD_INIT(network->routes);
52
53         network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
54         if (!network->addresses_by_section)
55                 return log_oom();
56
57         network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
58         if (!network->routes_by_section)
59                 return log_oom();
60
61         network->filename = strdup(filename);
62         if (!network->filename)
63                 return log_oom();
64
65         r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0", config_item_perf_lookup,
66                         (void*) network_gperf_lookup, false, false, network);
67         if (r < 0) {
68                 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
69                 return r;
70         } else
71                 log_debug("Parsed configuration file %s", filename);
72
73         LIST_PREPEND(networks, manager->networks, network);
74         network = NULL;
75
76         return 0;
77 }
78
79 int network_load(Manager *manager) {
80         Network *network;
81         char **files, **f;
82         int r;
83
84         assert(manager);
85
86         while ((network = manager->networks))
87                 network_free(network);
88
89         r = conf_files_list_strv(&files, ".network", NULL, (const char **)manager->network_dirs);
90         if (r < 0) {
91                 log_error("failed to enumerate network files: %s", strerror(-r));
92                 return r;
93         }
94
95         STRV_FOREACH_BACKWARDS(f, files) {
96                 r = network_load_one(manager, *f);
97                 if (r < 0)
98                         return r;
99         }
100
101         strv_free(files);
102
103         return 0;
104 }
105
106 void network_free(Network *network) {
107         Route *route;
108         Address *address;
109
110         if (!network)
111                 return;
112
113         free(network->filename);
114
115         free(network->match_mac);
116         free(network->match_path);
117         free(network->match_driver);
118         free(network->match_type);
119         free(network->match_name);
120
121         free(network->description);
122
123         while ((route = network->routes))
124                 route_free(route);
125
126         while ((address = network->addresses))
127                 address_free(address);
128
129         hashmap_free(network->addresses_by_section);
130         hashmap_free(network->routes_by_section);
131
132         LIST_REMOVE(networks, network->manager->networks, network);
133
134         free(network);
135 }
136
137 int network_get(Manager *manager, struct udev_device *device, Network **ret) {
138         Network *network;
139
140         assert(manager);
141         assert(device);
142         assert(ret);
143
144         if (manager_should_reload(manager))
145                 manager_load_config(manager);
146
147         LIST_FOREACH(networks, network, manager->networks) {
148                 if (net_match_config(network->match_mac, network->match_path,
149                                         network->match_driver, network->match_type,
150                                         network->match_name,
151                                         udev_device_get_sysattr_value(device, "address"),
152                                         udev_device_get_property_value(device, "ID_PATH"),
153                                         udev_device_get_driver(device),
154                                         udev_device_get_devtype(device),
155                                         udev_device_get_sysname(device))) {
156                         log_debug("Network file %s applies to link %s",
157                                         network->filename,
158                                         udev_device_get_sysname(device));
159                         *ret = network;
160                         return 0;
161                 }
162         }
163
164         *ret = NULL;
165
166         return -ENOENT;
167 }
168
169 int network_apply(Manager *manager, Network *network, Link *link) {
170         int r;
171
172         log_info("Network '%s' being applied to link '%s'",
173                         network->description, link->ifname);
174
175         link->network = network;
176
177         r = link_configure(link);
178         if (r < 0)
179                 return r;
180
181         return 0;
182 }
183
184 int config_parse_bridge(const char *unit,
185                 const char *filename,
186                 unsigned line,
187                 const char *section,
188                 unsigned section_line,
189                 const char *lvalue,
190                 int ltype,
191                 const char *rvalue,
192                 void *data,
193                 void *userdata) {
194         Network *network = userdata;
195         Bridge *bridge;
196         int r;
197
198         assert(filename);
199         assert(lvalue);
200         assert(rvalue);
201         assert(data);
202
203         r = bridge_get(network->manager, rvalue, &bridge);
204         if (r < 0) {
205                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
206                            "Bridge is invalid, ignoring assignment: %s", rvalue);
207                 return 0;
208         }
209
210         network->bridge = bridge;
211
212         return 0;
213 }