]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-search-domain.c
425a46334948c7531cc37877c69f06c52fe7135a
[thirdparty/systemd.git] / src / resolve / resolved-dns-search-domain.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
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
9 int 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 = new0(DnsSearchDomain, 1);
37 if (!d)
38 return -ENOMEM;
39
40 d->n_ref = 1;
41 d->manager = m;
42 d->type = type;
43 d->name = TAKE_PTR(normalized);
44
45 switch (type) {
46
47 case DNS_SEARCH_DOMAIN_LINK:
48 d->link = l;
49 LIST_APPEND(domains, l->search_domains, d);
50 l->n_search_domains++;
51 break;
52
53 case DNS_SERVER_SYSTEM:
54 LIST_APPEND(domains, m->search_domains, d);
55 m->n_search_domains++;
56 break;
57
58 default:
59 assert_not_reached("Unknown search domain type");
60 }
61
62 d->linked = true;
63
64 if (ret)
65 *ret = d;
66
67 return 0;
68 }
69
70 static DnsSearchDomain* dns_search_domain_free(DnsSearchDomain *d) {
71 assert(d);
72
73 free(d->name);
74 return mfree(d);
75 }
76
77 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsSearchDomain, dns_search_domain, dns_search_domain_free);
78
79 void dns_search_domain_unlink(DnsSearchDomain *d) {
80 assert(d);
81 assert(d->manager);
82
83 if (!d->linked)
84 return;
85
86 switch (d->type) {
87
88 case DNS_SEARCH_DOMAIN_LINK:
89 assert(d->link);
90 assert(d->link->n_search_domains > 0);
91 LIST_REMOVE(domains, d->link->search_domains, d);
92 d->link->n_search_domains--;
93 break;
94
95 case DNS_SEARCH_DOMAIN_SYSTEM:
96 assert(d->manager->n_search_domains > 0);
97 LIST_REMOVE(domains, d->manager->search_domains, d);
98 d->manager->n_search_domains--;
99 break;
100 }
101
102 d->linked = false;
103
104 dns_search_domain_unref(d);
105 }
106
107 void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) {
108 DnsSearchDomain *tail;
109
110 assert(d);
111
112 if (!d->marked)
113 return;
114
115 d->marked = false;
116
117 if (!d->linked || !d->domains_next)
118 return;
119
120 switch (d->type) {
121
122 case DNS_SEARCH_DOMAIN_LINK:
123 assert(d->link);
124 LIST_FIND_TAIL(domains, d, tail);
125 LIST_REMOVE(domains, d->link->search_domains, d);
126 LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d);
127 break;
128
129 case DNS_SEARCH_DOMAIN_SYSTEM:
130 LIST_FIND_TAIL(domains, d, tail);
131 LIST_REMOVE(domains, d->manager->search_domains, d);
132 LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d);
133 break;
134
135 default:
136 assert_not_reached("Unknown search domain type");
137 }
138 }
139
140 void dns_search_domain_unlink_all(DnsSearchDomain *first) {
141 DnsSearchDomain *next;
142
143 if (!first)
144 return;
145
146 next = first->domains_next;
147 dns_search_domain_unlink(first);
148
149 dns_search_domain_unlink_all(next);
150 }
151
152 void dns_search_domain_unlink_marked(DnsSearchDomain *first) {
153 DnsSearchDomain *next;
154
155 if (!first)
156 return;
157
158 next = first->domains_next;
159
160 if (first->marked)
161 dns_search_domain_unlink(first);
162
163 dns_search_domain_unlink_marked(next);
164 }
165
166 void dns_search_domain_mark_all(DnsSearchDomain *first) {
167 if (!first)
168 return;
169
170 first->marked = true;
171 dns_search_domain_mark_all(first->domains_next);
172 }
173
174 int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) {
175 DnsSearchDomain *d;
176 int r;
177
178 assert(name);
179 assert(ret);
180
181 LIST_FOREACH(domains, d, first) {
182
183 r = dns_name_equal(name, d->name);
184 if (r < 0)
185 return r;
186 if (r > 0) {
187 *ret = d;
188 return 1;
189 }
190 }
191
192 *ret = NULL;
193 return 0;
194 }