/src/systemd/src/resolve/resolved-dns-search-domain.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | |
3 | | #include "sd-json.h" |
4 | | |
5 | | #include "alloc-util.h" |
6 | | #include "dns-domain.h" |
7 | | #include "resolved-dns-delegate.h" |
8 | | #include "resolved-dns-search-domain.h" |
9 | | #include "resolved-link.h" |
10 | | #include "resolved-manager.h" |
11 | | |
12 | | int dns_search_domain_new( |
13 | | Manager *m, |
14 | | DnsSearchDomain **ret, |
15 | | DnsSearchDomainType type, |
16 | | Link *link, |
17 | | DnsDelegate *delegate, |
18 | 0 | const char *name) { |
19 | |
|
20 | 0 | _cleanup_free_ char *normalized = NULL; |
21 | 0 | DnsSearchDomain *d; |
22 | 0 | int r; |
23 | |
|
24 | 0 | assert(m); |
25 | 0 | assert((type == DNS_SEARCH_DOMAIN_LINK) == !!link); |
26 | 0 | assert((type == DNS_SEARCH_DOMAIN_DELEGATE) == !!delegate); |
27 | 0 | assert(name); |
28 | |
|
29 | 0 | r = dns_name_normalize(name, 0, &normalized); |
30 | 0 | if (r < 0) |
31 | 0 | return r; |
32 | | |
33 | 0 | if (link) { |
34 | 0 | if (link->n_search_domains >= LINK_SEARCH_DOMAINS_MAX) |
35 | 0 | return -E2BIG; |
36 | 0 | } else if (delegate) { |
37 | 0 | if (delegate->n_search_domains >= DELEGATE_SEARCH_DOMAINS_MAX) |
38 | 0 | return -E2BIG; |
39 | 0 | } else { |
40 | 0 | if (m->n_search_domains >= MANAGER_SEARCH_DOMAINS_MAX) |
41 | 0 | return -E2BIG; |
42 | 0 | } |
43 | | |
44 | 0 | d = new(DnsSearchDomain, 1); |
45 | 0 | if (!d) |
46 | 0 | return -ENOMEM; |
47 | | |
48 | 0 | *d = (DnsSearchDomain) { |
49 | 0 | .n_ref = 1, |
50 | 0 | .manager = m, |
51 | 0 | .type = type, |
52 | 0 | .name = TAKE_PTR(normalized), |
53 | 0 | }; |
54 | |
|
55 | 0 | switch (type) { |
56 | | |
57 | 0 | case DNS_SEARCH_DOMAIN_LINK: |
58 | 0 | d->link = link; |
59 | 0 | LIST_APPEND(domains, link->search_domains, d); |
60 | 0 | link->n_search_domains++; |
61 | 0 | break; |
62 | | |
63 | 0 | case DNS_SEARCH_DOMAIN_SYSTEM: |
64 | 0 | LIST_APPEND(domains, m->search_domains, d); |
65 | 0 | m->n_search_domains++; |
66 | 0 | break; |
67 | | |
68 | 0 | case DNS_SEARCH_DOMAIN_DELEGATE: |
69 | 0 | d->delegate = delegate; |
70 | 0 | LIST_APPEND(domains, delegate->search_domains, d); |
71 | 0 | delegate->n_search_domains++; |
72 | 0 | break; |
73 | | |
74 | 0 | default: |
75 | 0 | assert_not_reached(); |
76 | 0 | } |
77 | | |
78 | 0 | d->linked = true; |
79 | |
|
80 | 0 | if (ret) |
81 | 0 | *ret = d; |
82 | |
|
83 | 0 | return 0; |
84 | 0 | } |
85 | | |
86 | 0 | static DnsSearchDomain* dns_search_domain_free(DnsSearchDomain *d) { |
87 | 0 | assert(d); |
88 | |
|
89 | 0 | free(d->name); |
90 | 0 | return mfree(d); |
91 | 0 | } |
92 | | |
93 | 0 | DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsSearchDomain, dns_search_domain, dns_search_domain_free); Unexecuted instantiation: dns_search_domain_ref Unexecuted instantiation: dns_search_domain_unref |
94 | 0 |
|
95 | 0 | void dns_search_domain_unlink(DnsSearchDomain *d) { |
96 | 0 | assert(d); |
97 | 0 | assert(d->manager); |
98 | |
|
99 | 0 | if (!d->linked) |
100 | 0 | return; |
101 | | |
102 | 0 | switch (d->type) { |
103 | | |
104 | 0 | case DNS_SEARCH_DOMAIN_LINK: |
105 | 0 | assert(d->link); |
106 | 0 | assert(d->link->n_search_domains > 0); |
107 | 0 | LIST_REMOVE(domains, d->link->search_domains, d); |
108 | 0 | d->link->n_search_domains--; |
109 | 0 | break; |
110 | | |
111 | 0 | case DNS_SEARCH_DOMAIN_SYSTEM: |
112 | 0 | assert(d->manager->n_search_domains > 0); |
113 | 0 | LIST_REMOVE(domains, d->manager->search_domains, d); |
114 | 0 | d->manager->n_search_domains--; |
115 | 0 | break; |
116 | | |
117 | 0 | case DNS_SEARCH_DOMAIN_DELEGATE: |
118 | 0 | assert(d->delegate); |
119 | 0 | assert(d->delegate->n_search_domains > 0); |
120 | 0 | LIST_REMOVE(domains, d->delegate->search_domains, d); |
121 | 0 | d->delegate->n_search_domains--; |
122 | 0 | break; |
123 | 0 | } |
124 | | |
125 | 0 | d->linked = false; |
126 | |
|
127 | 0 | dns_search_domain_unref(d); |
128 | 0 | } |
129 | | |
130 | 0 | void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) { |
131 | 0 | DnsSearchDomain *tail; |
132 | |
|
133 | 0 | assert(d); |
134 | |
|
135 | 0 | if (!d->marked) |
136 | 0 | return; |
137 | | |
138 | 0 | d->marked = false; |
139 | |
|
140 | 0 | if (!d->linked || !d->domains_next) |
141 | 0 | return; |
142 | | |
143 | 0 | switch (d->type) { |
144 | | |
145 | 0 | case DNS_SEARCH_DOMAIN_LINK: |
146 | 0 | assert(d->link); |
147 | 0 | tail = LIST_FIND_TAIL(domains, d); |
148 | 0 | LIST_REMOVE(domains, d->link->search_domains, d); |
149 | 0 | LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d); |
150 | 0 | break; |
151 | | |
152 | 0 | case DNS_SEARCH_DOMAIN_SYSTEM: |
153 | 0 | tail = LIST_FIND_TAIL(domains, d); |
154 | 0 | LIST_REMOVE(domains, d->manager->search_domains, d); |
155 | 0 | LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d); |
156 | 0 | break; |
157 | | |
158 | 0 | case DNS_SEARCH_DOMAIN_DELEGATE: |
159 | 0 | assert(d->delegate); |
160 | 0 | tail = LIST_FIND_TAIL(domains, d); |
161 | 0 | LIST_REMOVE(domains, d->delegate->search_domains, d); |
162 | 0 | LIST_INSERT_AFTER(domains, d->delegate->search_domains, tail, d); |
163 | 0 | break; |
164 | | |
165 | 0 | default: |
166 | 0 | assert_not_reached(); |
167 | 0 | } |
168 | 0 | } |
169 | | |
170 | 0 | void dns_search_domain_unlink_all(DnsSearchDomain *first) { |
171 | 0 | DnsSearchDomain *next; |
172 | |
|
173 | 0 | if (!first) |
174 | 0 | return; |
175 | | |
176 | 0 | next = first->domains_next; |
177 | 0 | dns_search_domain_unlink(first); |
178 | |
|
179 | 0 | dns_search_domain_unlink_all(next); |
180 | 0 | } |
181 | | |
182 | 0 | bool dns_search_domain_unlink_marked(DnsSearchDomain *first) { |
183 | 0 | DnsSearchDomain *next; |
184 | 0 | bool changed; |
185 | |
|
186 | 0 | if (!first) |
187 | 0 | return false; |
188 | | |
189 | 0 | next = first->domains_next; |
190 | |
|
191 | 0 | if (first->marked) { |
192 | 0 | dns_search_domain_unlink(first); |
193 | 0 | changed = true; |
194 | 0 | } else |
195 | 0 | changed = false; |
196 | |
|
197 | 0 | return dns_search_domain_unlink_marked(next) || changed; |
198 | 0 | } |
199 | | |
200 | 0 | void dns_search_domain_mark_all(DnsSearchDomain *first) { |
201 | 0 | if (!first) |
202 | 0 | return; |
203 | | |
204 | 0 | first->marked = true; |
205 | 0 | dns_search_domain_mark_all(first->domains_next); |
206 | 0 | } |
207 | | |
208 | 0 | int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) { |
209 | 0 | int r; |
210 | |
|
211 | 0 | assert(name); |
212 | 0 | assert(ret); |
213 | |
|
214 | 0 | LIST_FOREACH(domains, d, first) { |
215 | |
|
216 | 0 | r = dns_name_equal(name, d->name); |
217 | 0 | if (r < 0) |
218 | 0 | return r; |
219 | 0 | if (r > 0) { |
220 | 0 | *ret = d; |
221 | 0 | return 1; |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | 0 | *ret = NULL; |
226 | 0 | return 0; |
227 | 0 | } |
228 | | |
229 | 0 | int dns_search_domain_dump_to_json(DnsSearchDomain *domain, sd_json_variant **ret) { |
230 | 0 | int ifindex = 0; |
231 | |
|
232 | 0 | assert(domain); |
233 | 0 | assert(ret); |
234 | |
|
235 | 0 | if (domain->type == DNS_SEARCH_DOMAIN_LINK) { |
236 | 0 | assert(domain->link); |
237 | 0 | ifindex = domain->link->ifindex; |
238 | 0 | } |
239 | |
|
240 | 0 | return sd_json_buildo( |
241 | 0 | ret, |
242 | 0 | SD_JSON_BUILD_PAIR_STRING("name", domain->name), |
243 | 0 | SD_JSON_BUILD_PAIR_BOOLEAN("routeOnly", domain->route_only), |
244 | 0 | SD_JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", SD_JSON_BUILD_UNSIGNED(ifindex))); |
245 | 0 | } |