blob: 3df4ab85d1c84b74797062124abe538cab55217f [file] [log] [blame]
Simon Kelley2bb73af2013-04-24 17:38:19 +01001/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
2
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 Kelley48fd1c42013-04-25 09:49:38 +010080 /* swap . or : for - */
81 for (p = tail; *p; p++)
82 if (*p == '-')
83 {
84 if (prot == AF_INET)
85 *p = '.';
Simon Kelley2bb73af2013-04-24 17:38:19 +010086#ifdef HAVE_IPV6
Simon Kelley48fd1c42013-04-25 09:49:38 +010087 else
88 *p = ':';
Simon Kelley2bb73af2013-04-24 17:38:19 +010089#endif
Simon Kelley48fd1c42013-04-25 09:49:38 +010090 }
91
92 if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
Simon Kelley2bb73af2013-04-24 17:38:19 +010093 {
94 if (prot == AF_INET)
95 {
96 if (!c->is6 &&
97 ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
98 ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
Simon Kelley48fd1c42013-04-25 09:49:38 +010099 found = 1;
Simon Kelley2bb73af2013-04-24 17:38:19 +0100100 }
101#ifdef HAVE_IPV6
102 else
103 {
104 u64 addrpart = addr6part(&addr->addr.addr6);
105
106 if (c->is6 &&
107 is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
108 addrpart >= addr6part(&c->start6) &&
109 addrpart <= addr6part(&c->end6))
Simon Kelley48fd1c42013-04-25 09:49:38 +0100110 found = 1;
Simon Kelley2bb73af2013-04-24 17:38:19 +0100111 }
112#endif
113 }
Simon Kelley48fd1c42013-04-25 09:49:38 +0100114
115 /* restore name */
116 for (p = tail; *p; p++)
117 if (*p == '.' || *p == ':')
118 *p = '-';
119
120 *p = '.';
121
122 if (found)
123 return 1;
124 }
Simon Kelley2bb73af2013-04-24 17:38:19 +0100125
Simon Kelley48fd1c42013-04-25 09:49:38 +0100126 return 0;
Simon Kelley2bb73af2013-04-24 17:38:19 +0100127}
128
129
130int is_rev_synth(int flag, struct all_addr *addr, char *name)
131{
132 struct cond_domain *c;
133
134 if (flag & F_IPV4 && (c = search_domain(addr->addr.addr4, daemon->synth_domains)))
135 {
136 char *p;
137
Simon Kelley48fd1c42013-04-25 09:49:38 +0100138 *name = 0;
139 if (c->prefix)
140 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
141
142 inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
Simon Kelley2bb73af2013-04-24 17:38:19 +0100143 for (p = name; *p; p++)
144 if (*p == '.')
145 *p = '-';
146
147 strncat(name, ".", MAXDNAME);
148 strncat(name, c->domain, MAXDNAME);
149
150 return 1;
151 }
152
153#ifdef HAVE_IPV6
154 if (flag & F_IPV6 && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains)))
155 {
156 char *p;
157
Simon Kelley48fd1c42013-04-25 09:49:38 +0100158 *name = 0;
159 if (c->prefix)
160 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
161
162 inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
Simon Kelley2bb73af2013-04-24 17:38:19 +0100163
164 /* IPv6 presentation address can start with ":", but valid domain names
165 cannot start with "-" so prepend a zero in that case. */
Simon Kelley48fd1c42013-04-25 09:49:38 +0100166 if (!c->prefix && *name == ':')
Simon Kelley2bb73af2013-04-24 17:38:19 +0100167 {
168 *name = '0';
169 inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
170 }
171
172 for (p = name; *p; p++)
173 if (*p == ':')
174 *p = '-';
175
176 strncat(name, ".", MAXDNAME);
177 strncat(name, c->domain, MAXDNAME);
178
179 return 1;
180 }
181#endif
182
183 return 0;
184}
185
186
187static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
188{
189 for (; c; c = c->next)
190 if (!c->is6 &&
191 ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
192 ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
193 return c;
194
195 return NULL;
196}
197
198char *get_domain(struct in_addr addr)
199{
200 struct cond_domain *c;
201
202 if ((c = search_domain(addr, daemon->cond_domain)))
203 return c->domain;
204
205 return daemon->domain_suffix;
206}
207
208#ifdef HAVE_IPV6
209static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
210{
211 u64 addrpart = addr6part(addr);
212
213 for (; c; c = c->next)
214 if (c->is6 &&
215 is_same_net6(addr, &c->start6, 64) &&
216 addrpart >= addr6part(&c->start6) &&
217 addrpart <= addr6part(&c->end6))
218 return c;
219
220 return NULL;
221}
222
223char *get_domain6(struct in6_addr *addr)
224{
225 struct cond_domain *c;
226
Simon Kelley6bd109a2013-07-27 15:11:44 +0100227 if (addr && (c = search_domain6(addr, daemon->cond_domain)))
Simon Kelley2bb73af2013-04-24 17:38:19 +0100228 return c->domain;
229
230 return daemon->domain_suffix;
231}
232#endif