chiark / gitweb /
resolved: be a bit more communicative about conflicts
[elogind.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 "conf-parser.h"
23
24 #include "resolved-conf.h"
25
26 int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) {
27         const char *word, *state;
28         size_t length;
29         DnsServer *first;
30         int r;
31
32         assert(m);
33         assert(string);
34
35         first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers;
36
37         FOREACH_WORD_QUOTED(word, length, string, state) {
38                 char buffer[length+1];
39                 int family;
40                 union in_addr_union addr;
41                 bool found = false;
42                 DnsServer *s;
43
44                 memcpy(buffer, word, length);
45                 buffer[length] = 0;
46
47                 r = in_addr_from_string_auto(buffer, &family, &addr);
48                 if (r < 0) {
49                         log_warning("Ignoring invalid DNS address '%s'", buffer);
50                         continue;
51                 }
52
53                 /* Filter out duplicates */
54                 LIST_FOREACH(servers, s, first)
55                         if (s->family == family && in_addr_equal(family, &s->address, &addr)) {
56                                 found = true;
57                                 break;
58                         }
59
60                 if (found)
61                         continue;
62
63                 r = dns_server_new(m, NULL, type, NULL, family, &addr);
64                 if (r < 0)
65                         return r;
66         }
67
68         return 0;
69 }
70
71 int config_parse_dnsv(
72                 const char *unit,
73                 const char *filename,
74                 unsigned line,
75                 const char *section,
76                 unsigned section_line,
77                 const char *lvalue,
78                 int ltype,
79                 const char *rvalue,
80                 void *data,
81                 void *userdata) {
82
83         Manager *m = userdata;
84         DnsServer **l;
85         int r;
86
87         assert(filename);
88         assert(lvalue);
89         assert(rvalue);
90         assert(m);
91
92         if (ltype == DNS_SERVER_FALLBACK)
93                 l = &m->fallback_dns_servers;
94         else
95                 l = &m->dns_servers;
96
97         if (isempty(rvalue)) {
98
99                 /* Empty assignment means clear the list */
100                 while (*l)
101                         dns_server_free(*l);
102
103         } else {
104
105                 /* Otherwise add to the list */
106                 r = manager_parse_dns_server(m, ltype, rvalue);
107                 if (r < 0) {
108                         log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue);
109                         return 0;
110                 }
111         }
112
113         /* If we have a manual setting, then we stop reading
114          * /etc/resolv.conf */
115         if (ltype == DNS_SERVER_SYSTEM)
116                 m->read_resolv_conf = false;
117
118         return 0;
119 }
120
121 int config_parse_support(
122                 const char *unit,
123                 const char *filename,
124                 unsigned line,
125                 const char *section,
126                 unsigned section_line,
127                 const char *lvalue,
128                 int ltype,
129                 const char *rvalue,
130                 void *data,
131                 void *userdata) {
132
133         Manager *m = userdata;
134         Support support, *v = data;
135         int r;
136
137         assert(filename);
138         assert(lvalue);
139         assert(rvalue);
140         assert(m);
141
142         support = support_from_string(rvalue);
143         if (support < 0) {
144                 r = parse_boolean(rvalue);
145                 if (r < 0) {
146                         log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse support level '%s'. Ignoring.", rvalue);
147                         return 0;
148                 }
149
150                 support = r ? SUPPORT_YES : SUPPORT_NO;
151         }
152
153         *v = support;
154         return 0;
155 }
156
157 int manager_parse_config_file(Manager *m) {
158         assert(m);
159
160         return config_parse(NULL, "/etc/systemd/resolved.conf", NULL,
161                             "Resolve\0",
162                             config_item_perf_lookup, resolved_gperf_lookup,
163                             false, false, true, m);
164 }