blob: 3dc96abc0130516e73ec790ce4b5a2c5700a9f73 [file] [log] [blame]
Simon Kelley2a8710a2020-01-05 16:40:06 +00001/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
Simon Kelley2bb73af2013-04-24 17:38:19 +01002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17#include "dnsmasq.h"
18
19
20static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
Simon Kelley2bb73af2013-04-24 17:38:19 +010021static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
Simon Kelley2bb73af2013-04-24 17:38:19 +010022
23
Simon Kelleycc921df2019-01-02 22:48:59 +000024int is_name_synthetic(int flags, char *name, union all_addr *addr)
Simon Kelley2bb73af2013-04-24 17:38:19 +010025{
26 char *p;
27 struct cond_domain *c = NULL;
Simon Kelleyee875042018-10-23 22:10:17 +010028 int prot = (flags & F_IPV6) ? AF_INET6 : AF_INET;
Simon Kelley2bb73af2013-04-24 17:38:19 +010029
Simon Kelley48fd1c42013-04-25 09:49:38 +010030 for (c = daemon->synth_domains; c; c = c->next)
Simon Kelley2bb73af2013-04-24 17:38:19 +010031 {
Simon Kelley48fd1c42013-04-25 09:49:38 +010032 int found = 0;
33 char *tail, *pref;
Simon Kelley2bb73af2013-04-24 17:38:19 +010034
Simon Kelley48fd1c42013-04-25 09:49:38 +010035 for (tail = name, pref = c->prefix; *tail != 0 && pref && *pref != 0; tail++, pref++)
36 {
37 unsigned int c1 = (unsigned char) *pref;
38 unsigned int c2 = (unsigned char) *tail;
39
40 if (c1 >= 'A' && c1 <= 'Z')
41 c1 += 'a' - 'A';
42 if (c2 >= 'A' && c2 <= 'Z')
43 c2 += 'a' - 'A';
44
45 if (c1 != c2)
46 break;
47 }
48
49 if (pref && *pref != 0)
50 continue; /* prefix match fail */
Simon Kelley6b2b5642018-03-10 18:12:04 +000051
52 if (c->indexed)
Simon Kelley48fd1c42013-04-25 09:49:38 +010053 {
Simon Kelley6b2b5642018-03-10 18:12:04 +000054 for (p = tail; *p; p++)
55 {
56 char c = *p;
57
58 if (c < '0' || c > '9')
59 break;
60 }
Simon Kelley48fd1c42013-04-25 09:49:38 +010061
Simon Kelley6b2b5642018-03-10 18:12:04 +000062 if (*p != '.')
Simon Kelley48fd1c42013-04-25 09:49:38 +010063 continue;
64
Simon Kelley6b2b5642018-03-10 18:12:04 +000065 *p = 0;
66
67 if (hostname_isequal(c->domain, p+1))
68 {
69 if (prot == AF_INET)
70 {
71 unsigned int index = atoi(tail);
72
73 if (!c->is6 &&
74 index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
75 {
Simon Kelleycc921df2019-01-02 22:48:59 +000076 addr->addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
Simon Kelley6b2b5642018-03-10 18:12:04 +000077 found = 1;
78 }
Simon Kelleyee875042018-10-23 22:10:17 +010079 }
Simon Kelley6b2b5642018-03-10 18:12:04 +000080 else
81 {
82 u64 index = atoll(tail);
83
84 if (c->is6 &&
85 index <= addr6part(&c->end6) - addr6part(&c->start6))
86 {
87 u64 start = addr6part(&c->start6);
Simon Kelleycc921df2019-01-02 22:48:59 +000088 addr->addr6 = c->start6;
89 setaddr6part(&addr->addr6, start + index);
Simon Kelley6b2b5642018-03-10 18:12:04 +000090 found = 1;
91 }
92 }
Simon Kelley6b2b5642018-03-10 18:12:04 +000093 }
Simon Kelley6d950992016-08-11 23:38:54 +010094 }
95 else
Simon Kelley6d950992016-08-11 23:38:54 +010096 {
Simon Kelley6b2b5642018-03-10 18:12:04 +000097 /* NB, must not alter name if we return zero */
Simon Kelley6d950992016-08-11 23:38:54 +010098 for (p = tail; *p; p++)
Simon Kelley6b2b5642018-03-10 18:12:04 +000099 {
100 char c = *p;
101
102 if ((c >='0' && c <= '9') || c == '-')
103 continue;
104
Simon Kelley6b2b5642018-03-10 18:12:04 +0000105 if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
106 continue;
Simon Kelley6b2b5642018-03-10 18:12:04 +0000107
108 break;
109 }
110
111 if (*p != '.')
112 continue;
113
114 *p = 0;
115
Simon Kelley6b2b5642018-03-10 18:12:04 +0000116 if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
117 {
118 /* special hack for v4-mapped. */
119 memcpy(tail, "::ffff:", 7);
120 for (p = tail + 7; *p; p++)
121 if (*p == '-')
122 *p = '.';
123 }
124 else
Simon Kelley6b2b5642018-03-10 18:12:04 +0000125 {
126 /* swap . or : for - */
127 for (p = tail; *p; p++)
128 if (*p == '-')
129 {
130 if (prot == AF_INET)
131 *p = '.';
Simon Kelley6b2b5642018-03-10 18:12:04 +0000132 else
133 *p = ':';
Simon Kelley6b2b5642018-03-10 18:12:04 +0000134 }
135 }
136
137 if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
138 {
139 if (prot == AF_INET)
140 {
141 if (!c->is6 &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000142 ntohl(addr->addr4.s_addr) >= ntohl(c->start.s_addr) &&
143 ntohl(addr->addr4.s_addr) <= ntohl(c->end.s_addr))
Simon Kelley6b2b5642018-03-10 18:12:04 +0000144 found = 1;
145 }
Simon Kelley6b2b5642018-03-10 18:12:04 +0000146 else
147 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000148 u64 addrpart = addr6part(&addr->addr6);
Simon Kelley6b2b5642018-03-10 18:12:04 +0000149
150 if (c->is6 &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000151 is_same_net6(&addr->addr6, &c->start6, 64) &&
Simon Kelley6b2b5642018-03-10 18:12:04 +0000152 addrpart >= addr6part(&c->start6) &&
153 addrpart <= addr6part(&c->end6))
154 found = 1;
155 }
Simon Kelley6b2b5642018-03-10 18:12:04 +0000156 }
157
Simon Kelley6d950992016-08-11 23:38:54 +0100158 }
159
Simon Kelley48fd1c42013-04-25 09:49:38 +0100160 /* restore name */
161 for (p = tail; *p; p++)
162 if (*p == '.' || *p == ':')
163 *p = '-';
164
165 *p = '.';
Simon Kelley6b2b5642018-03-10 18:12:04 +0000166
167
Simon Kelley48fd1c42013-04-25 09:49:38 +0100168 if (found)
169 return 1;
170 }
Simon Kelley2bb73af2013-04-24 17:38:19 +0100171
Simon Kelley48fd1c42013-04-25 09:49:38 +0100172 return 0;
Simon Kelley2bb73af2013-04-24 17:38:19 +0100173}
174
175
Simon Kelleycc921df2019-01-02 22:48:59 +0000176int is_rev_synth(int flag, union all_addr *addr, char *name)
Simon Kelley2bb73af2013-04-24 17:38:19 +0100177{
178 struct cond_domain *c;
179
Simon Kelleycc921df2019-01-02 22:48:59 +0000180 if (flag & F_IPV4 && (c = search_domain(addr->addr4, daemon->synth_domains)))
Simon Kelley2bb73af2013-04-24 17:38:19 +0100181 {
182 char *p;
183
Simon Kelley48fd1c42013-04-25 09:49:38 +0100184 *name = 0;
Simon Kelley6b2b5642018-03-10 18:12:04 +0000185 if (c->indexed)
186 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000187 unsigned int index = ntohl(addr->addr4.s_addr) - ntohl(c->start.s_addr);
Simon Kelley6b2b5642018-03-10 18:12:04 +0000188 snprintf(name, MAXDNAME, "%s%u", c->prefix ? c->prefix : "", index);
189 }
190 else
191 {
192 if (c->prefix)
193 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
Simon Kelley48fd1c42013-04-25 09:49:38 +0100194
Simon Kelleycc921df2019-01-02 22:48:59 +0000195 inet_ntop(AF_INET, &addr->addr4, name + strlen(name), ADDRSTRLEN);
Simon Kelley6b2b5642018-03-10 18:12:04 +0000196 for (p = name; *p; p++)
197 if (*p == '.')
198 *p = '-';
199 }
200
Simon Kelley2bb73af2013-04-24 17:38:19 +0100201 strncat(name, ".", MAXDNAME);
202 strncat(name, c->domain, MAXDNAME);
203
204 return 1;
205 }
206
Simon Kelleycc921df2019-01-02 22:48:59 +0000207 if ((flag & F_IPV6) && (c = search_domain6(&addr->addr6, daemon->synth_domains)))
Simon Kelley2bb73af2013-04-24 17:38:19 +0100208 {
209 char *p;
210
Simon Kelley48fd1c42013-04-25 09:49:38 +0100211 *name = 0;
Simon Kelley6b2b5642018-03-10 18:12:04 +0000212 if (c->indexed)
Simon Kelley2bb73af2013-04-24 17:38:19 +0100213 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000214 u64 index = addr6part(&addr->addr6) - addr6part(&c->start6);
Simon Kelley6b2b5642018-03-10 18:12:04 +0000215 snprintf(name, MAXDNAME, "%s%llu", c->prefix ? c->prefix : "", index);
Simon Kelley2bb73af2013-04-24 17:38:19 +0100216 }
Simon Kelley6b2b5642018-03-10 18:12:04 +0000217 else
218 {
219 if (c->prefix)
220 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
221
Simon Kelleycc921df2019-01-02 22:48:59 +0000222 inet_ntop(AF_INET6, &addr->addr6, name + strlen(name), ADDRSTRLEN);
Simon Kelley2bb73af2013-04-24 17:38:19 +0100223
Simon Kelley6b2b5642018-03-10 18:12:04 +0000224 /* IPv6 presentation address can start with ":", but valid domain names
225 cannot start with "-" so prepend a zero in that case. */
226 if (!c->prefix && *name == ':')
227 {
228 *name = '0';
Simon Kelleycc921df2019-01-02 22:48:59 +0000229 inet_ntop(AF_INET6, &addr->addr6, name+1, ADDRSTRLEN);
Simon Kelley6b2b5642018-03-10 18:12:04 +0000230 }
231
232 /* V4-mapped have periods.... */
233 for (p = name; *p; p++)
234 if (*p == ':' || *p == '.')
235 *p = '-';
236
237 }
Simon Kelley2bb73af2013-04-24 17:38:19 +0100238
239 strncat(name, ".", MAXDNAME);
240 strncat(name, c->domain, MAXDNAME);
241
242 return 1;
243 }
Simon Kelley2bb73af2013-04-24 17:38:19 +0100244
245 return 0;
246}
247
248
249static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
250{
251 for (; c; c = c->next)
252 if (!c->is6 &&
253 ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
254 ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
255 return c;
256
257 return NULL;
258}
259
260char *get_domain(struct in_addr addr)
261{
262 struct cond_domain *c;
263
264 if ((c = search_domain(addr, daemon->cond_domain)))
265 return c->domain;
266
267 return daemon->domain_suffix;
268}
269
Simon Kelleyee875042018-10-23 22:10:17 +0100270
Simon Kelley2bb73af2013-04-24 17:38:19 +0100271static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
272{
273 u64 addrpart = addr6part(addr);
274
275 for (; c; c = c->next)
276 if (c->is6 &&
277 is_same_net6(addr, &c->start6, 64) &&
278 addrpart >= addr6part(&c->start6) &&
279 addrpart <= addr6part(&c->end6))
280 return c;
281
282 return NULL;
283}
284
285char *get_domain6(struct in6_addr *addr)
286{
287 struct cond_domain *c;
288
Simon Kelley6bd109a2013-07-27 15:11:44 +0100289 if (addr && (c = search_domain6(addr, daemon->cond_domain)))
Simon Kelley2bb73af2013-04-24 17:38:19 +0100290 return c->domain;
291
292 return daemon->domain_suffix;
293}