summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-01-05 23:01:10 +0100
committerTom Gundersen <teg@jklm.no>2014-01-12 15:37:21 +0100
commit3bef724f7e7f7eaca69881548b06e221b77d7031 (patch)
tree0b17e5a43d7e5c5d07dc696d23d4c829f9ab7200
parent924fe4304af981ffd849346b4a1d415f11e9dd79 (diff)
networkd: generate resolv.conf
This adds support to generate a basic resolv.conf in /run/systemd/network. This file will not take any effect unless a symlink is created from /etc/resolv.conf. Nameservers received over DHCP takes precedence over statically configured ones. Note: /etc/resolv.conf is severely limited, so in the future we will likely rather provide a much more powerfull nss plugin (or something to that effect), but this should allow current users to function without any loss of functionality.
-rw-r--r--Makefile.am2
-rw-r--r--src/network/networkd-address.c37
-rw-r--r--src/network/networkd-gperf.gperf1
-rw-r--r--src/network/networkd-link.c8
-rw-r--r--src/network/networkd-manager.c75
-rw-r--r--src/network/networkd-network.c8
-rw-r--r--src/network/networkd.c7
-rw-r--r--src/network/networkd.h8
8 files changed, 146 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 65b445ec5..b4bb6e1e3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4107,6 +4107,7 @@ systemd_networkd_LDADD = \
4107 libsystemd-id128-internal.la \ 4107 libsystemd-id128-internal.la \
4108 libsystemd-rtnl.la \ 4108 libsystemd-rtnl.la \
4109 libsystemd-dhcp.la \ 4109 libsystemd-dhcp.la \
4110 libsystemd-label.la \
4110 libsystemd-shared.la 4111 libsystemd-shared.la
4111 4112
4112nodist_systemunit_DATA += \ 4113nodist_systemunit_DATA += \
@@ -4133,6 +4134,7 @@ test_network_LDADD = \
4133 libsystemd-daemon-internal.la \ 4134 libsystemd-daemon-internal.la \
4134 libsystemd-rtnl.la \ 4135 libsystemd-rtnl.la \
4135 libsystemd-dhcp.la \ 4136 libsystemd-dhcp.la \
4137 libsystemd-label.la \
4136 libsystemd-shared.la 4138 libsystemd-shared.la
4137 4139
4138tests += \ 4140tests += \
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 8a7163005..7d06cf887 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -190,6 +190,43 @@ int address_configure(Address *address, Link *link,
190 return 0; 190 return 0;
191} 191}
192 192
193int config_parse_dns(const char *unit,
194 const char *filename,
195 unsigned line,
196 const char *section,
197 unsigned section_line,
198 const char *lvalue,
199 int ltype,
200 const char *rvalue,
201 void *data,
202 void *userdata) {
203 Address **dns = data;
204 _cleanup_address_free_ Address *n = NULL;
205 int r;
206
207 assert(filename);
208 assert(section);
209 assert(lvalue);
210 assert(rvalue);
211 assert(data);
212
213 r = address_new_dynamic(&n);
214 if (r < 0)
215 return r;
216
217 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
218 if (r < 0) {
219 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
220 "DNS address is invalid, ignoring assignment: %s", rvalue);
221 return 0;
222 }
223
224 *dns = n;
225 n = NULL;
226
227 return 0;
228}
229
193int config_parse_address(const char *unit, 230int config_parse_address(const char *unit,
194 const char *filename, 231 const char *filename,
195 unsigned line, 232 unsigned line,
diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
index f1594d56c..92954a836 100644
--- a/src/network/networkd-gperf.gperf
+++ b/src/network/networkd-gperf.gperf
@@ -25,6 +25,7 @@ Network.Bridge, config_parse_bridge, 0, offsetof(Networ
25Network.DHCP, config_parse_bool, 0, offsetof(Network, dhcp) 25Network.DHCP, config_parse_bool, 0, offsetof(Network, dhcp)
26Network.Address, config_parse_address, 0, 0 26Network.Address, config_parse_address, 0, 0
27Network.Gateway, config_parse_gateway, 0, 0 27Network.Gateway, config_parse_gateway, 0, 0
28Network.DNS, config_parse_dns, 0, offsetof(Network, dns)
28Address.Address, config_parse_address, 0, 0 29Address.Address, config_parse_address, 0, 0
29Address.Label, config_parse_label, 0, 0 30Address.Label, config_parse_label, 0, 0
30Route.Gateway, config_parse_gateway, 0, 0 31Route.Gateway, config_parse_gateway, 0, 0
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 25d92c8aa..5dd8e9100 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -378,6 +378,7 @@ static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
378 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) { 378 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
379 _cleanup_address_free_ Address *addr = NULL; 379 _cleanup_address_free_ Address *addr = NULL;
380 _cleanup_route_free_ Route *rt = NULL; 380 _cleanup_route_free_ Route *rt = NULL;
381 struct in_addr **nameservers;
381 382
382 log_struct_link(LOG_INFO, link, 383 log_struct_link(LOG_INFO, link,
383 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u", 384 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
@@ -420,6 +421,13 @@ static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
420 addr = NULL; 421 addr = NULL;
421 rt = NULL; 422 rt = NULL;
422 423
424 r = sd_dhcp_client_get_dns(client, &nameservers);
425 if (r >= 0) {
426 r = manager_update_resolv_conf(link->manager);
427 if (r < 0)
428 log_error("Failed to update resolv.conf");
429 }
430
423 link_enter_set_addresses(link); 431 link_enter_set_addresses(link);
424 } 432 }
425 433
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index c9ce1d6a1..f02eed1a5 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -19,10 +19,13 @@
19 along with systemd; If not, see <http://www.gnu.org/licenses/>. 19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/ 20 ***/
21 21
22#include <resolv.h>
23
22#include "path-util.h" 24#include "path-util.h"
23#include "networkd.h" 25#include "networkd.h"
24#include "libudev-private.h" 26#include "libudev-private.h"
25#include "udev-util.h" 27#include "udev-util.h"
28#include "mkdir.h"
26 29
27const char* const network_dirs[] = { 30const char* const network_dirs[] = {
28 "/etc/systemd/network", 31 "/etc/systemd/network",
@@ -276,3 +279,75 @@ int manager_rtnl_listen(Manager *m) {
276 279
277 return 0; 280 return 0;
278} 281}
282
283static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
284 char buf[INET6_ADDRSTRLEN];
285 const char *address;
286
287 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
288 if (!address) {
289 log_warning("Invalid DNS address. Ignoring.");
290 return;
291 }
292
293 if (*count == MAXNS)
294 fputs("# Too many dynamic name servers configured, the "
295 "following entries will be ignored\n", f);
296
297 fprintf(f, "nameserver %s\n", address);
298
299 (*count) ++;
300}
301
302int manager_update_resolv_conf(Manager *m) {
303 _cleanup_free_ char *temp_path = NULL;
304 _cleanup_fclose_ FILE *f = NULL;
305 Link *link;
306 Iterator i;
307 unsigned count = 0;
308 int r;
309
310 assert(m);
311
312 r = mkdir_safe_label("/run/systemd/network", 0755, 0, 0);
313 if (r < 0)
314 return r;
315
316 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
317 if (r < 0)
318 return r;
319
320 fchmod(fileno(f), 0644);
321
322 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n", f);
323
324 HASHMAP_FOREACH(link, m->links, i) {
325 if (link->dhcp) {
326 struct in_addr **nameservers;
327
328 r = sd_dhcp_client_get_dns(link->dhcp, &nameservers);
329 if (r >= 0) {
330 unsigned j;
331
332 for (j = 0; nameservers[j]; j++)
333 append_dns(f, nameservers[j], AF_INET, &count);
334 }
335 }
336 }
337
338 HASHMAP_FOREACH(link, m->links, i)
339 if (link->network && link->network->dns)
340 append_dns(f, &link->network->dns->in_addr.in,
341 link->network->dns->family, &count);
342
343 fflush(f);
344
345 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
346 r = -errno;
347 unlink("/run/systemd/network/resolv.conf");
348 unlink(temp_path);
349 return r;
350 }
351
352 return 0;
353}
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index f2546440c..f98731001 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -144,6 +144,8 @@ void network_free(Network *network) {
144 144
145 free(network->description); 145 free(network->description);
146 146
147 address_free(network->dns);
148
147 while ((route = network->static_routes)) 149 while ((route = network->static_routes))
148 route_free(route); 150 route_free(route);
149 151
@@ -197,6 +199,12 @@ int network_apply(Manager *manager, Network *network, Link *link) {
197 if (r < 0) 199 if (r < 0)
198 return r; 200 return r;
199 201
202 if (network->dns) {
203 r = manager_update_resolv_conf(manager);
204 if (r < 0)
205 return r;
206 }
207
200 return 0; 208 return 0;
201} 209}
202 210
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 360afba98..055200cb0 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -60,6 +60,13 @@ int main(int argc, char *argv[]) {
60 if (r < 0) 60 if (r < 0)
61 goto out; 61 goto out;
62 62
63
64 /* write out empty resolv.conf to avoid a
65 * dangling symlink */
66 r = manager_update_resolv_conf(m);
67 if (r < 0)
68 goto out;
69
63 sd_notify(false, 70 sd_notify(false,
64 "READY=1\n" 71 "READY=1\n"
65 "STATUS=Processing requests..."); 72 "STATUS=Processing requests...");
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 55181f2bb..607feba0e 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -88,6 +88,7 @@ struct Network {
88 88
89 LIST_HEAD(Address, static_addresses); 89 LIST_HEAD(Address, static_addresses);
90 LIST_HEAD(Route, static_routes); 90 LIST_HEAD(Route, static_routes);
91 Address *dns;
91 92
92 Hashmap *addresses_by_section; 93 Hashmap *addresses_by_section;
93 Hashmap *routes_by_section; 94 Hashmap *routes_by_section;
@@ -157,6 +158,7 @@ struct Link {
157 158
158 Route *dhcp_route; 159 Route *dhcp_route;
159 Address *dhcp_address; 160 Address *dhcp_address;
161 Address *dns;
160 162
161 LinkState state; 163 LinkState state;
162 164
@@ -195,6 +197,8 @@ int manager_udev_listen(Manager *m);
195 197
196int manager_rtnl_listen(Manager *m); 198int manager_rtnl_listen(Manager *m);
197 199
200int manager_update_resolv_conf(Manager *m);
201
198DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); 202DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
199#define _cleanup_manager_free_ _cleanup_(manager_freep) 203#define _cleanup_manager_free_ _cleanup_(manager_freep)
200 204
@@ -258,6 +262,10 @@ int address_drop(Address *address, Link *link, sd_rtnl_message_handler_t callbac
258DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); 262DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
259#define _cleanup_address_free_ _cleanup_(address_freep) 263#define _cleanup_address_free_ _cleanup_(address_freep)
260 264
265int config_parse_dns(const char *unit, const char *filename, unsigned line,
266 const char *section, unsigned section_line, const char *lvalue,
267 int ltype, const char *rvalue, void *data, void *userdata);
268
261int config_parse_address(const char *unit, const char *filename, unsigned line, 269int config_parse_address(const char *unit, const char *filename, unsigned line,
262 const char *section, unsigned section_line, const char *lvalue, 270 const char *section, unsigned section_line, const char *lvalue,
263 int ltype, const char *rvalue, void *data, void *userdata); 271 int ltype, const char *rvalue, void *data, void *userdata);