]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/resolve/resolved-dns-search-domain.c
resolved: optimize change notification handling away if bus calls set the same values...
[thirdparty/systemd.git] / src / resolve / resolved-dns-search-domain.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include "alloc-util.h"
4#include "dns-domain.h"
5#include "resolved-dns-search-domain.h"
6#include "resolved-link.h"
7#include "resolved-manager.h"
8
9int dns_search_domain_new(
10 Manager *m,
11 DnsSearchDomain **ret,
12 DnsSearchDomainType type,
13 Link *l,
14 const char *name) {
15
16 _cleanup_free_ char *normalized = NULL;
17 DnsSearchDomain *d;
18 int r;
19
20 assert(m);
21 assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l);
22 assert(name);
23
24 r = dns_name_normalize(name, 0, &normalized);
25 if (r < 0)
26 return r;
27
28 if (l) {
29 if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX)
30 return -E2BIG;
31 } else {
32 if (m->n_search_domains >= MANAGER_SEARCH_DOMAINS_MAX)
33 return -E2BIG;
34 }
35
36 d = new(DnsSearchDomain, 1);
37 if (!d)
38 return -ENOMEM;
39
40 *d = (DnsSearchDomain) {
41 .n_ref = 1,
42 .manager = m,
43 .type = type,
44 .name = TAKE_PTR(normalized),
45 };
46
47 switch (type) {
48
49 case DNS_SEARCH_DOMAIN_LINK:
50 d->link = l;
51 LIST_APPEND(domains, l->search_domains, d);
52 l->n_search_domains++;
53 break;
54
55 case DNS_SERVER_SYSTEM:
56 LIST_APPEND(domains, m->search_domains, d);
57 m->n_search_domains++;
58 break;
59
60 default:
61 assert_not_reached("Unknown search domain type");
62 }
63
64 d->linked = true;
65
66 if (ret)
67 *ret = d;
68
69 return 0;
70}
71
72static DnsSearchDomain* dns_search_domain_free(DnsSearchDomain *d) {
73 assert(d);
74
75 free(d->name);
76 return mfree(d);
77}
78
79DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsSearchDomain, dns_search_domain, dns_search_domain_free);
80
81void dns_search_domain_unlink(DnsSearchDomain *d) {
82 assert(d);
83 assert(d->manager);
84
85 if (!d->linked)
86 return;
87
88 switch (d->type) {
89
90 case DNS_SEARCH_DOMAIN_LINK:
91 assert(d->link);
92 assert(d->link->n_search_domains > 0);
93 LIST_REMOVE(domains, d->link->search_domains, d);
94 d->link->n_search_domains--;
95 break;
96
97 case DNS_SEARCH_DOMAIN_SYSTEM:
98 assert(d->manager->n_search_domains > 0);
99 LIST_REMOVE(domains, d->manager->search_domains, d);
100 d->manager->n_search_domains--;
101 break;
102 }
103
104 d->linked = false;
105
106 dns_search_domain_unref(d);
107}
108
109void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) {
110 DnsSearchDomain *tail;
111
112 assert(d);
113
114 if (!d->marked)
115 return;
116
117 d->marked = false;
118
119 if (!d->linked || !d->domains_next)
120 return;
121
122 switch (d->type) {
123
124 case DNS_SEARCH_DOMAIN_LINK:
125 assert(d->link);
126 LIST_FIND_TAIL(domains, d, tail);
127 LIST_REMOVE(domains, d->link->search_domains, d);
128 LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d);
129 break;
130
131 case DNS_SEARCH_DOMAIN_SYSTEM:
132 LIST_FIND_TAIL(domains, d, tail);
133 LIST_REMOVE(domains, d->manager->search_domains, d);
134 LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d);
135 break;
136
137 default:
138 assert_not_reached("Unknown search domain type");
139 }
140}
141
142void dns_search_domain_unlink_all(DnsSearchDomain *first) {
143 DnsSearchDomain *next;
144
145 if (!first)
146 return;
147
148 next = first->domains_next;
149 dns_search_domain_unlink(first);
150
151 dns_search_domain_unlink_all(next);
152}
153
154bool dns_search_domain_unlink_marked(DnsSearchDomain *first) {
155 DnsSearchDomain *next;
156 bool changed;
157
158 if (!first)
159 return false;
160
161 next = first->domains_next;
162
163 if (first->marked) {
164 dns_search_domain_unlink(first);
165 changed = true;
166 } else
167 changed = false;
168
169 return changed || dns_search_domain_unlink_marked(next);
170}
171
172void dns_search_domain_mark_all(DnsSearchDomain *first) {
173 if (!first)
174 return;
175
176 first->marked = true;
177 dns_search_domain_mark_all(first->domains_next);
178}
179
180int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) {
181 DnsSearchDomain *d;
182 int r;
183
184 assert(name);
185 assert(ret);
186
187 LIST_FOREACH(domains, d, first) {
188
189 r = dns_name_equal(name, d->name);
190 if (r < 0)
191 return r;
192 if (r > 0) {
193 *ret = d;
194 return 1;
195 }
196 }
197
198 *ret = NULL;
199 return 0;
200}