]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
sd-dhcp-client/networkd: add interface MTU support
[thirdparty/systemd.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 #include "util.h"
28
29 static int network_load_one(Manager *manager, const char *filename) {
30 _cleanup_network_free_ Network *network = NULL;
31 _cleanup_fclose_ FILE *file = NULL;
32 Route *route;
33 Address *address;
34 int r;
35
36 assert(manager);
37 assert(filename);
38
39 file = fopen(filename, "re");
40 if (!file) {
41 if (errno == ENOENT)
42 return 0;
43 else
44 return errno;
45 }
46
47 network = new0(Network, 1);
48 if (!network)
49 return log_oom();
50
51 network->manager = manager;
52
53 LIST_HEAD_INIT(network->static_addresses);
54 LIST_HEAD_INIT(network->static_routes);
55
56 network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
57 if (!network->addresses_by_section)
58 return log_oom();
59
60 network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
61 if (!network->routes_by_section)
62 return log_oom();
63
64 network->filename = strdup(filename);
65 if (!network->filename)
66 return log_oom();
67
68 network->dhcp_dns = true;
69 network->dhcp_mtu = true;
70
71 r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
72 (void*) network_gperf_lookup, false, false, network);
73 if (r < 0) {
74 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
75 return r;
76 }
77
78 LIST_PREPEND(networks, manager->networks, network);
79
80 LIST_FOREACH(static_routes, route, network->static_routes) {
81 if (!route->family) {
82 log_warning("Route section without Gateway field configured in %s. "
83 "Ignoring", filename);
84 return 0;
85 }
86
87 if (route->dst_family && route->family != route->dst_family) {
88 log_warning("Route section with conflicting Gateway and Destination address "
89 "family configured in %s. Ignoring", filename);
90 return 0;
91 }
92 }
93
94 LIST_FOREACH(static_addresses, address, network->static_addresses) {
95 if (!address->family) {
96 log_warning("Address section without Address field configured in %s. "
97 "Ignoring", filename);
98 return 0;
99 }
100 }
101
102 network = NULL;
103
104 return 0;
105 }
106
107 int network_load(Manager *manager) {
108 Network *network;
109 _cleanup_strv_free_ char **files = NULL;
110 char **f;
111 int r;
112
113 assert(manager);
114
115 while ((network = manager->networks))
116 network_free(network);
117
118 r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
119 if (r < 0) {
120 log_error("Failed to enumerate network files: %s", strerror(-r));
121 return r;
122 }
123
124 STRV_FOREACH_BACKWARDS(f, files) {
125 r = network_load_one(manager, *f);
126 if (r < 0)
127 return r;
128 }
129
130 return 0;
131 }
132
133 void network_free(Network *network) {
134 Route *route;
135 Address *address;
136
137 if (!network)
138 return;
139
140 free(network->filename);
141
142 free(network->match_mac);
143 free(network->match_path);
144 free(network->match_driver);
145 free(network->match_type);
146 free(network->match_name);
147
148 free(network->description);
149
150 address_free(network->dns);
151
152 while ((route = network->static_routes))
153 route_free(route);
154
155 while ((address = network->static_addresses))
156 address_free(address);
157
158 hashmap_free(network->addresses_by_section);
159 hashmap_free(network->routes_by_section);
160
161 if (network->manager && network->manager->networks)
162 LIST_REMOVE(networks, network->manager->networks, network);
163
164 free(network);
165 }
166
167 int network_get(Manager *manager, struct udev_device *device, Network **ret) {
168 Network *network;
169
170 assert(manager);
171 assert(device);
172 assert(ret);
173
174 LIST_FOREACH(networks, network, manager->networks) {
175 if (net_match_config(network->match_mac, network->match_path,
176 network->match_driver, network->match_type,
177 network->match_name,
178 udev_device_get_sysattr_value(device, "address"),
179 udev_device_get_property_value(device, "ID_PATH"),
180 udev_device_get_driver(device),
181 udev_device_get_devtype(device),
182 udev_device_get_sysname(device))) {
183 log_debug("%s: found matching network '%s'",
184 udev_device_get_sysname(device),
185 network->filename);
186 *ret = network;
187 return 0;
188 }
189 }
190
191 *ret = NULL;
192
193 return -ENOENT;
194 }
195
196 int network_apply(Manager *manager, Network *network, Link *link) {
197 int r;
198
199 link->network = network;
200
201 r = link_configure(link);
202 if (r < 0)
203 return r;
204
205 if (network->dns) {
206 r = manager_update_resolv_conf(manager);
207 if (r < 0)
208 return r;
209 }
210
211 return 0;
212 }
213
214 int config_parse_bridge(const char *unit,
215 const char *filename,
216 unsigned line,
217 const char *section,
218 unsigned section_line,
219 const char *lvalue,
220 int ltype,
221 const char *rvalue,
222 void *data,
223 void *userdata) {
224 Network *network = userdata;
225 Bridge *bridge;
226 int r;
227
228 assert(filename);
229 assert(lvalue);
230 assert(rvalue);
231 assert(data);
232
233 r = bridge_get(network->manager, rvalue, &bridge);
234 if (r < 0) {
235 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
236 "Bridge is invalid, ignoring assignment: %s", rvalue);
237 return 0;
238 }
239
240 network->bridge = bridge;
241
242 return 0;
243 }