blob: 853dc172266a435d9166fb109c001f9e2c9f2ee0 [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 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);
21#ifdef HAVE_IPV6
22static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
23#endif
24
25
26int is_name_synthetic(int flags, char *name, struct all_addr *addr)
27{
28 char *p;
29 struct cond_domain *c = NULL;
30 int prot = AF_INET;
31
32#ifdef HAVE_IPV6
33 if (flags & F_IPV6)
34 prot = AF_INET6;
35#endif
36
Simon Kelley48fd1c42013-04-25 09:49:38 +010037 for (c = daemon->synth_domains; c; c = c->next)
Simon Kelley2bb73af2013-04-24 17:38:19 +010038 {
Simon Kelley48fd1c42013-04-25 09:49:38 +010039 int found = 0;
40 char *tail, *pref;
Simon Kelley2bb73af2013-04-24 17:38:19 +010041
Simon Kelley48fd1c42013-04-25 09:49:38 +010042 for (tail = name, pref = c->prefix; *tail != 0 && pref && *pref != 0; tail++, pref++)
43 {
44 unsigned int c1 = (unsigned char) *pref;
45 unsigned int c2 = (unsigned char) *tail;
46
47 if (c1 >= 'A' && c1 <= 'Z')
48 c1 += 'a' - 'A';
49 if (c2 >= 'A' && c2 <= 'Z')
50 c2 += 'a' - 'A';
51
52 if (c1 != c2)
53 break;
54 }
55
56 if (pref && *pref != 0)
57 continue; /* prefix match fail */
58
59 /* NB, must not alter name if we return zero */
60 for (p = tail; *p; p++)
61 {
62 char c = *p;
63
64 if ((c >='0' && c <= '9') || c == '-')
65 continue;
66
67#ifdef HAVE_IPV6
68 if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
69 continue;
70#endif
71
72 break;
73 }
74
75 if (*p != '.')
Simon Kelley2bb73af2013-04-24 17:38:19 +010076 continue;
77
Simon Kelley48fd1c42013-04-25 09:49:38 +010078 *p = 0;
Simon Kelley2bb73af2013-04-24 17:38:19 +010079
Simon Kelley6d950992016-08-11 23:38:54 +010080 #ifdef HAVE_IPV6
81 if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
82 {
83 /* special hack for v4-mapped. */
84 memcpy(tail, "::ffff:", 7);
85 for (p = tail + 7; *p; p++)
86 if (*p == '-')
Simon Kelley48fd1c42013-04-25 09:49:38 +010087 *p = '.';
Simon Kelley6d950992016-08-11 23:38:54 +010088 }
89 else
Simon Kelley2bb73af2013-04-24 17:38:19 +010090#endif
Simon Kelley6d950992016-08-11 23:38:54 +010091 {
92 /* swap . or : for - */
93 for (p = tail; *p; p++)
94 if (*p == '-')
95 {
96 if (prot == AF_INET)
97 *p = '.';
98#ifdef HAVE_IPV6
99 else
100 *p = ':';
101#endif
102 }
103 }
104
Simon Kelley48fd1c42013-04-25 09:49:38 +0100105 if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
Simon Kelley2bb73af2013-04-24 17:38:19 +0100106 {
107 if (prot == AF_INET)
108 {
109 if (!c->is6 &&
110 ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
111 ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
Simon Kelley48fd1c42013-04-25 09:49:38 +0100112 found = 1;
Simon Kelley2bb73af2013-04-24 17:38:19 +0100113 }
114#ifdef HAVE_IPV6
115 else
116 {
117 u64 addrpart = addr6part(&addr->addr.addr6);
118
119 if (c->is6 &&
120 is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
121 addrpart >= addr6part(&c->start6) &&
122 addrpart <= addr6part(&c->end6))
Simon Kelley48fd1c42013-04-25 09:49:38 +0100123 found = 1;
Simon Kelley2bb73af2013-04-24 17:38:19 +0100124 }
125#endif
126 }
Simon Kelley48fd1c42013-04-25 09:49:38 +0100127
128 /* restore name */
129 for (p = tail; *p; p++)
130 if (*p == '.' || *p == ':')
131 *p = '-';
132
133 *p = '.';
134
135 if (found)
136 return 1;
137 }
Simon Kelley2bb73af2013-04-24 17:38:19 +0100138
Simon Kelley48fd1c42013-04-25 09:49:38 +0100139 return 0;
Simon Kelley2bb73af2013-04-24 17:38:19 +0100140}
141
142
143int is_rev_synth(int flag, struct all_addr *addr, char *name)
144{
145 struct cond_domain *c;
146
147 if (flag & F_IPV4 && (c = search_domain(addr->addr.addr4, daemon->synth_domains)))
148 {
149 char *p;
150
Simon Kelley48fd1c42013-04-25 09:49:38 +0100151 *name = 0;
152 if (c->prefix)
153 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
154
155 inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
Simon Kelley2bb73af2013-04-24 17:38:19 +0100156 for (p = name; *p; p++)
157 if (*p == '.')
158 *p = '-';
159
160 strncat(name, ".", MAXDNAME);
161 strncat(name, c->domain, MAXDNAME);
162
163 return 1;
164 }
165
166#ifdef HAVE_IPV6
167 if (flag & F_IPV6 && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains)))
168 {
169 char *p;
170
Simon Kelley48fd1c42013-04-25 09:49:38 +0100171 *name = 0;
172 if (c->prefix)
173 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
174
175 inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
Simon Kelley2bb73af2013-04-24 17:38:19 +0100176
177 /* IPv6 presentation address can start with ":", but valid domain names
178 cannot start with "-" so prepend a zero in that case. */
Simon Kelley48fd1c42013-04-25 09:49:38 +0100179 if (!c->prefix && *name == ':')
Simon Kelley2bb73af2013-04-24 17:38:19 +0100180 {
181 *name = '0';
182 inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
183 }
184
Simon Kelley6d950992016-08-11 23:38:54 +0100185 /* V4-mapped have periods.... */
Simon Kelley2bb73af2013-04-24 17:38:19 +0100186 for (p = name; *p; p++)
Simon Kelley6d950992016-08-11 23:38:54 +0100187 if (*p == ':' || *p == '.')
Simon Kelley2bb73af2013-04-24 17:38:19 +0100188 *p = '-';
189
190 strncat(name, ".", MAXDNAME);
191 strncat(name, c->domain, MAXDNAME);
192
193 return 1;
194 }
195#endif
196
197 return 0;
198}
199
200
201static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
202{
203 for (; c; c = c->next)
204 if (!c->is6 &&
205 ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
206 ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
207 return c;
208
209 return NULL;
210}
211
212char *get_domain(struct in_addr addr)
213{
214 struct cond_domain *c;
215
216 if ((c = search_domain(addr, daemon->cond_domain)))
217 return c->domain;
218
219 return daemon->domain_suffix;
220}
221
222#ifdef HAVE_IPV6
223static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
224{
225 u64 addrpart = addr6part(addr);
226
227 for (; c; c = c->next)
228 if (c->is6 &&
229 is_same_net6(addr, &c->start6, 64) &&
230 addrpart >= addr6part(&c->start6) &&
231 addrpart <= addr6part(&c->end6))
232 return c;
233
234 return NULL;
235}
236
237char *get_domain6(struct in6_addr *addr)
238{
239 struct cond_domain *c;
240
Simon Kelley6bd109a2013-07-27 15:11:44 +0100241 if (addr && (c = search_domain6(addr, daemon->cond_domain)))
Simon Kelley2bb73af2013-04-24 17:38:19 +0100242 return c->domain;
243
244 return daemon->domain_suffix;
245}
246#endif