]> git.ipfire.org Git - thirdparty/systemd.git/blame - 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
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
a51c1048
LP
2
3#include "alloc-util.h"
4#include "dns-domain.h"
5#include "resolved-dns-search-domain.h"
be28f72d
DDM
6#include "resolved-link.h"
7#include "resolved-manager.h"
a51c1048
LP
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;
eed857b7 17 DnsSearchDomain *d;
a51c1048
LP
18 int r;
19
20 assert(m);
21 assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l);
22 assert(name);
23
7470cc4c 24 r = dns_name_normalize(name, 0, &normalized);
a51c1048
LP
25 if (r < 0)
26 return r;
27
eed857b7
LP
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
1ed31408 36 d = new(DnsSearchDomain, 1);
a51c1048
LP
37 if (!d)
38 return -ENOMEM;
39
1ed31408
LP
40 *d = (DnsSearchDomain) {
41 .n_ref = 1,
42 .manager = m,
43 .type = type,
44 .name = TAKE_PTR(normalized),
45 };
a51c1048
LP
46
47 switch (type) {
48
49 case DNS_SEARCH_DOMAIN_LINK:
50 d->link = l;
eed857b7
LP
51 LIST_APPEND(domains, l->search_domains, d);
52 l->n_search_domains++;
a51c1048
LP
53 break;
54
55 case DNS_SERVER_SYSTEM:
eed857b7
LP
56 LIST_APPEND(domains, m->search_domains, d);
57 m->n_search_domains++;
a51c1048
LP
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
8301aa0b
YW
72static DnsSearchDomain* dns_search_domain_free(DnsSearchDomain *d) {
73 assert(d);
a51c1048
LP
74
75 free(d->name);
6b430fdb 76 return mfree(d);
a51c1048
LP
77}
78
8301aa0b
YW
79DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsSearchDomain, dns_search_domain, dns_search_domain_free);
80
a51c1048
LP
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);
eed857b7 92 assert(d->link->n_search_domains > 0);
a51c1048 93 LIST_REMOVE(domains, d->link->search_domains, d);
eed857b7 94 d->link->n_search_domains--;
a51c1048
LP
95 break;
96
97 case DNS_SEARCH_DOMAIN_SYSTEM:
eed857b7 98 assert(d->manager->n_search_domains > 0);
a51c1048 99 LIST_REMOVE(domains, d->manager->search_domains, d);
eed857b7 100 d->manager->n_search_domains--;
a51c1048
LP
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
cbf23f38 154bool dns_search_domain_unlink_marked(DnsSearchDomain *first) {
a51c1048 155 DnsSearchDomain *next;
cbf23f38 156 bool changed;
a51c1048
LP
157
158 if (!first)
cbf23f38 159 return false;
a51c1048
LP
160
161 next = first->domains_next;
162
cbf23f38 163 if (first->marked) {
a51c1048 164 dns_search_domain_unlink(first);
cbf23f38
LP
165 changed = true;
166 } else
167 changed = false;
a51c1048 168
cbf23f38 169 return changed || dns_search_domain_unlink_marked(next);
a51c1048
LP
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}