chiark / gitweb /
e0e3878f75bb79b4addc0452a67002a5b14e1a66
[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->static_addresses);
51         LIST_HEAD_INIT(network->static_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         }
71
72         LIST_PREPEND(networks, manager->networks, network);
73         network = NULL;
74
75         return 0;
76 }
77
78 int network_load(Manager *manager) {
79         Network *network;
80         char **files, **f;
81         int r;
82
83         assert(manager);
84
85         while ((network = manager->networks))
86                 network_free(network);
87
88         r = conf_files_list_strv(&files, ".network", NULL, (const char **)manager->network_dirs);
89         if (r < 0) {
90                 log_error("Failed to enumerate network files: %s", strerror(-r));
91                 return r;
92         }
93
94         STRV_FOREACH_BACKWARDS(f, files) {
95                 r = network_load_one(manager, *f);
96                 if (r < 0)
97                         return r;
98         }
99
100         strv_free(files);
101
102         return 0;
103 }
104
105 void network_free(Network *network) {
106         Route *route;
107         Address *address;
108
109         if (!network)
110                 return;
111
112         free(network->filename);
113
114         free(network->match_mac);
115         free(network->match_path);
116         free(network->match_driver);
117         free(network->match_type);
118         free(network->match_name);
119
120         free(network->description);
121
122         while ((route = network->static_routes))
123                 route_free(route);
124
125         while ((address = network->static_addresses))
126                 address_free(address);
127
128         hashmap_free(network->addresses_by_section);
129         hashmap_free(network->routes_by_section);
130
131         LIST_REMOVE(networks, network->manager->networks, network);
132
133         free(network);
134 }
135
136 int network_get(Manager *manager, struct udev_device *device, Network **ret) {
137         Network *network;
138
139         assert(manager);
140         assert(device);
141         assert(ret);
142
143         if (manager_should_reload(manager))
144                 manager_load_config(manager);
145
146         LIST_FOREACH(networks, network, manager->networks) {
147                 if (net_match_config(network->match_mac, network->match_path,
148                                         network->match_driver, network->match_type,
149                                         network->match_name,
150                                         udev_device_get_sysattr_value(device, "address"),
151                                         udev_device_get_property_value(device, "ID_PATH"),
152                                         udev_device_get_driver(device),
153                                         udev_device_get_devtype(device),
154                                         udev_device_get_sysname(device))) {
155                         log_debug("%s: found matching network '%s'",
156                                         udev_device_get_sysname(device),
157                                         network->filename);
158                         *ret = network;
159                         return 0;
160                 }
161         }
162
163         *ret = NULL;
164
165         return -ENOENT;
166 }
167
168 int network_apply(Manager *manager, Network *network, Link *link) {
169         int r;
170
171         link->network = network;
172
173         r = link_configure(link);
174         if (r < 0)
175                 return r;
176
177         return 0;
178 }
179
180 int config_parse_bridge(const char *unit,
181                 const char *filename,
182                 unsigned line,
183                 const char *section,
184                 unsigned section_line,
185                 const char *lvalue,
186                 int ltype,
187                 const char *rvalue,
188                 void *data,
189                 void *userdata) {
190         Network *network = userdata;
191         Bridge *bridge;
192         int r;
193
194         assert(filename);
195         assert(lvalue);
196         assert(rvalue);
197         assert(data);
198
199         r = bridge_get(network->manager, rvalue, &bridge);
200         if (r < 0) {
201                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
202                            "Bridge is invalid, ignoring assignment: %s", rvalue);
203                 return 0;
204         }
205
206         network->bridge = bridge;
207
208         return 0;
209 }