]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-conf.c
resolved: make sure order of dns servers is stable
[thirdparty/systemd.git] / src / resolve / resolved-conf.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 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 "alloc-util.h"
23 #include "conf-parser.h"
24 #include "def.h"
25 #include "extract-word.h"
26 #include "parse-util.h"
27 #include "resolved-conf.h"
28 #include "string-util.h"
29
30 int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
31 union in_addr_union address;
32 int family, r;
33 DnsServer *s;
34
35 assert(m);
36 assert(word);
37
38 r = in_addr_from_string_auto(word, &family, &address);
39 if (r < 0)
40 return r;
41
42 /* Filter out duplicates */
43 s = manager_find_dns_server(m, type, family, &address);
44 if (s) {
45 /*
46 * Drop the marker. This is used to find the servers
47 * that ceased to exist, see
48 * manager_mark_dns_servers() and
49 * manager_flush_marked_dns_servers().
50 */
51 dns_server_move_back_and_unmark(s);
52 return 0;
53 }
54
55 return dns_server_new(m, NULL, type, NULL, family, &address);
56 }
57
58 int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) {
59 int r;
60
61 assert(m);
62 assert(string);
63
64 for(;;) {
65 _cleanup_free_ char *word = NULL;
66
67 r = extract_first_word(&string, &word, NULL, 0);
68 if (r < 0)
69 return r;
70 if (r == 0)
71 break;
72
73 r = manager_add_dns_server_by_string(m, type, word);
74 if (r < 0) {
75 log_warning_errno(r, "Failed to add DNS server address '%s', ignoring.", word);
76 continue;
77 }
78 }
79
80 return 0;
81 }
82
83 int config_parse_dns_servers(
84 const char *unit,
85 const char *filename,
86 unsigned line,
87 const char *section,
88 unsigned section_line,
89 const char *lvalue,
90 int ltype,
91 const char *rvalue,
92 void *data,
93 void *userdata) {
94
95 Manager *m = userdata;
96 int r;
97
98 assert(filename);
99 assert(lvalue);
100 assert(rvalue);
101 assert(m);
102
103 if (isempty(rvalue))
104 /* Empty assignment means clear the list */
105 manager_flush_dns_servers(m, ltype);
106 else {
107 /* Otherwise, add to the list */
108 r = manager_parse_dns_server_string_and_warn(m, ltype, rvalue);
109 if (r < 0) {
110 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue);
111 return 0;
112 }
113 }
114
115 /* If we have a manual setting, then we stop reading
116 * /etc/resolv.conf */
117 if (ltype == DNS_SERVER_SYSTEM)
118 m->read_resolv_conf = false;
119 if (ltype == DNS_SERVER_FALLBACK)
120 m->need_builtin_fallbacks = false;
121
122 return 0;
123 }
124
125 int config_parse_support(
126 const char *unit,
127 const char *filename,
128 unsigned line,
129 const char *section,
130 unsigned section_line,
131 const char *lvalue,
132 int ltype,
133 const char *rvalue,
134 void *data,
135 void *userdata) {
136
137 Support support, *v = data;
138 int r;
139
140 assert(filename);
141 assert(lvalue);
142 assert(rvalue);
143
144 support = support_from_string(rvalue);
145 if (support < 0) {
146 r = parse_boolean(rvalue);
147 if (r < 0) {
148 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse support level '%s'. Ignoring.", rvalue);
149 return 0;
150 }
151
152 support = r ? SUPPORT_YES : SUPPORT_NO;
153 }
154
155 *v = support;
156 return 0;
157 }
158
159 int manager_parse_config_file(Manager *m) {
160 int r;
161
162 assert(m);
163
164 r = config_parse_many(PKGSYSCONFDIR "/resolved.conf",
165 CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
166 "Resolve\0",
167 config_item_perf_lookup, resolved_gperf_lookup,
168 false, m);
169 if (r < 0)
170 return r;
171
172 if (m->need_builtin_fallbacks) {
173 r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
174 if (r < 0)
175 return r;
176 }
177
178 return 0;
179
180 }