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
dns_search_domain_new(Manager * m,DnsSearchDomain ** ret,DnsSearchDomainType type,Link * l,const char * name)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 = 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();
62 }
63
64 d->linked = true;
65
66 if (ret)
67 *ret = d;
68
69 return 0;
70 }
71
dns_search_domain_free(DnsSearchDomain * d)72 static DnsSearchDomain* dns_search_domain_free(DnsSearchDomain *d) {
73 assert(d);
74
75 free(d->name);
76 return mfree(d);
77 }
78
79 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsSearchDomain, dns_search_domain, dns_search_domain_free);
80
dns_search_domain_unlink(DnsSearchDomain * d)81 void 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
dns_search_domain_move_back_and_unmark(DnsSearchDomain * d)109 void 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();
139 }
140 }
141
dns_search_domain_unlink_all(DnsSearchDomain * first)142 void 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
dns_search_domain_unlink_marked(DnsSearchDomain * first)154 bool 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 dns_search_domain_unlink_marked(next) || changed;
170 }
171
dns_search_domain_mark_all(DnsSearchDomain * first)172 void 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
dns_search_domain_find(DnsSearchDomain * first,const char * name,DnsSearchDomain ** ret)180 int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) {
181 int r;
182
183 assert(name);
184 assert(ret);
185
186 LIST_FOREACH(domains, d, first) {
187
188 r = dns_name_equal(name, d->name);
189 if (r < 0)
190 return r;
191 if (r > 0) {
192 *ret = d;
193 return 1;
194 }
195 }
196
197 *ret = NULL;
198 return 0;
199 }
200