]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-search-domain.c
resolved: add a generic DnsSearchDomain concept
[thirdparty/systemd.git] / src / resolve / resolved-dns-search-domain.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 Lennart Poettering
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 "dns-domain.h"
24 #include "resolved-dns-search-domain.h"
25
26 int dns_search_domain_new(
27 Manager *m,
28 DnsSearchDomain **ret,
29 DnsSearchDomainType type,
30 Link *l,
31 const char *name) {
32
33 _cleanup_free_ char *normalized = NULL;
34 DnsSearchDomain *d, *tail;
35 int r;
36
37 assert(m);
38 assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l);
39 assert(name);
40
41 r = dns_name_normalize(name, &normalized);
42 if (r < 0)
43 return r;
44
45 r = dns_name_root(normalized);
46 if (r < 0)
47 return r;
48 if (r > 0)
49 return -EINVAL;
50
51 d = new0(DnsSearchDomain, 1);
52 if (!d)
53 return -ENOMEM;
54
55 d->n_ref = 1;
56 d->manager = m;
57 d->type = type;
58 d->name = normalized;
59 normalized = NULL;
60
61 switch (type) {
62
63 case DNS_SEARCH_DOMAIN_LINK:
64 d->link = l;
65 LIST_FIND_TAIL(domains, l->search_domains, tail);
66 LIST_INSERT_AFTER(domains, l->search_domains, tail, d);
67 break;
68
69 case DNS_SERVER_SYSTEM:
70 LIST_FIND_TAIL(domains, m->search_domains, tail);
71 LIST_INSERT_AFTER(domains, m->search_domains, tail, d);
72 break;
73
74 default:
75 assert_not_reached("Unknown search domain type");
76 }
77
78 d->linked = true;
79
80 if (ret)
81 *ret = d;
82
83 return 0;
84 }
85
86 DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d) {
87 if (!d)
88 return NULL;
89
90 assert(d->n_ref > 0);
91 d->n_ref++;
92
93 return d;
94 }
95
96 DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) {
97 if (!d)
98 return NULL;
99
100 assert(d->n_ref > 0);
101 d->n_ref--;
102
103 if (d->n_ref > 0)
104 return NULL;
105
106 free(d->name);
107 free(d);
108
109 return NULL;
110 }
111
112 void dns_search_domain_unlink(DnsSearchDomain *d) {
113 assert(d);
114 assert(d->manager);
115
116 if (!d->linked)
117 return;
118
119 switch (d->type) {
120
121 case DNS_SEARCH_DOMAIN_LINK:
122 assert(d->link);
123 LIST_REMOVE(domains, d->link->search_domains, d);
124 break;
125
126 case DNS_SEARCH_DOMAIN_SYSTEM:
127 LIST_REMOVE(domains, d->manager->search_domains, d);
128 break;
129 }
130
131 d->linked = false;
132
133 dns_search_domain_unref(d);
134 }
135
136 void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) {
137 DnsSearchDomain *tail;
138
139 assert(d);
140
141 if (!d->marked)
142 return;
143
144 d->marked = false;
145
146 if (!d->linked || !d->domains_next)
147 return;
148
149 switch (d->type) {
150
151 case DNS_SEARCH_DOMAIN_LINK:
152 assert(d->link);
153 LIST_FIND_TAIL(domains, d, tail);
154 LIST_REMOVE(domains, d->link->search_domains, d);
155 LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d);
156 break;
157
158 case DNS_SEARCH_DOMAIN_SYSTEM:
159 LIST_FIND_TAIL(domains, d, tail);
160 LIST_REMOVE(domains, d->manager->search_domains, d);
161 LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d);
162 break;
163
164 default:
165 assert_not_reached("Unknown search domain type");
166 }
167 }
168
169 void dns_search_domain_unlink_all(DnsSearchDomain *first) {
170 DnsSearchDomain *next;
171
172 if (!first)
173 return;
174
175 next = first->domains_next;
176 dns_search_domain_unlink(first);
177
178 dns_search_domain_unlink_all(next);
179 }
180
181 void dns_search_domain_unlink_marked(DnsSearchDomain *first) {
182 DnsSearchDomain *next;
183
184 if (!first)
185 return;
186
187 next = first->domains_next;
188
189 if (first->marked)
190 dns_search_domain_unlink(first);
191
192 dns_search_domain_unlink_marked(next);
193 }
194
195 void dns_search_domain_mark_all(DnsSearchDomain *first) {
196 if (!first)
197 return;
198
199 first->marked = true;
200 dns_search_domain_mark_all(first->domains_next);
201 }
202
203 int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) {
204 DnsSearchDomain *d;
205 int r;
206
207 assert(name);
208 assert(ret);
209
210 LIST_FOREACH(domains, d, first) {
211
212 r = dns_name_equal(name, d->name);
213 if (r < 0)
214 return r;
215 if (r > 0) {
216 *ret = d;
217 return 1;
218 }
219 }
220
221 *ret = NULL;
222 return 0;
223 }