]>
Commit | Line | Data |
---|---|---|
f831e573 MF |
1 | From a7369bef8abd241c3d85633fa9c870943f091e76 Mon Sep 17 00:00:00 2001 |
2 | From: Ed Bardsley <ebardsley@google.com> | |
3 | Date: Wed, 5 Aug 2015 21:17:18 +0100 | |
4 | Subject: [PATCH] Enhance --add-subnet to allow arbitary subnet addresses. | |
5 | ||
6 | --- | |
7 | CHANGELOG | 4 ++++ | |
8 | man/dnsmasq.8 | 32 ++++++++++++++++++++----------- | |
9 | src/dnsmasq.h | 13 ++++++++++--- | |
10 | src/option.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- | |
11 | src/rfc1035.c | 39 +++++++++++++++++++++++++++++++------- | |
12 | 5 files changed, 121 insertions(+), 26 deletions(-) | |
13 | ||
14 | diff --git a/CHANGELOG b/CHANGELOG | |
15 | index 3f4026d..bbc2834 100644 | |
16 | --- a/CHANGELOG | |
17 | +++ b/CHANGELOG | |
18 | @@ -4,6 +4,10 @@ version 2.76 | |
19 | least, 0.0.0.0 accesses the local host, so could | |
20 | be targets for DNS rebinding. See RFC 5735 section 3 | |
21 | for details. Thanks to Stephen Röttger for the bug report. | |
22 | + | |
23 | + Enhance --add-subnet to allow arbitrary subnet addresses. | |
24 | + Thanks to Ed Barsley for the patch. | |
25 | + | |
26 | ||
27 | version 2.75 | |
28 | Fix reversion on 2.74 which caused 100% CPU use when a | |
29 | diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 | |
30 | index c8913b5..a23c898 100644 | |
31 | --- a/man/dnsmasq.8 | |
32 | +++ b/man/dnsmasq.8 | |
33 | @@ -604,17 +604,27 @@ experimental. Also note that exposing MAC addresses in this way may | |
34 | have security and privacy implications. The warning about caching | |
35 | given for --add-subnet applies to --add-mac too. | |
36 | .TP | |
37 | -.B --add-subnet[[=<IPv4 prefix length>],<IPv6 prefix length>] | |
38 | -Add the subnet address of the requestor to the DNS queries which are | |
39 | -forwarded upstream. The amount of the address forwarded depends on the | |
40 | -prefix length parameter: 32 (128 for IPv6) forwards the whole address, | |
41 | -zero forwards none of it but still marks the request so that no | |
42 | -upstream nameserver will add client address information either. The | |
43 | -default is zero for both IPv4 and IPv6. Note that upstream nameservers | |
44 | -may be configured to return different results based on this | |
45 | -information, but the dnsmasq cache does not take account. If a dnsmasq | |
46 | -instance is configured such that different results may be encountered, | |
47 | -caching should be disabled. | |
48 | +.B --add-subnet[[=[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 address>/]<IPv6 prefix length>]] | |
49 | +Add a subnet address to the DNS queries which are forwarded | |
50 | +upstream. If an address is specified in the flag, it will be used, | |
51 | +otherwise, the address of the requestor will be used. The amount of | |
52 | +the address forwarded depends on the prefix length parameter: 32 (128 | |
53 | +for IPv6) forwards the whole address, zero forwards none of it but | |
54 | +still marks the request so that no upstream nameserver will add client | |
55 | +address information either. The default is zero for both IPv4 and | |
56 | +IPv6. Note that upstream nameservers may be configured to return | |
57 | +different results based on this information, but the dnsmasq cache | |
58 | +does not take account. If a dnsmasq instance is configured such that | |
59 | +different results may be encountered, caching should be disabled. | |
60 | + | |
61 | +For example, | |
62 | +.B --add-subnet=24,96 | |
63 | +will add the /24 and /96 subnets of the requestor for IPv4 and IPv6 requestors, respectively. | |
64 | +.B --add-subnet=1.2.3.4/24 | |
65 | +will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors. | |
66 | +.B --add-subnet=1.2.3.4/24,1.2.3.4/24 | |
67 | +will add 1.2.3.0/24 for both IPv4 and IPv6 requestors. | |
68 | + | |
69 | .TP | |
70 | .B \-c, --cache-size=<cachesize> | |
71 | Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching. | |
72 | diff --git a/src/dnsmasq.h b/src/dnsmasq.h | |
73 | index cf1a782..f42acdb 100644 | |
74 | --- a/src/dnsmasq.h | |
75 | +++ b/src/dnsmasq.h | |
76 | @@ -541,6 +541,13 @@ struct iname { | |
77 | struct iname *next; | |
78 | }; | |
79 | ||
80 | +/* subnet parameters from command line */ | |
81 | +struct mysubnet { | |
82 | + union mysockaddr addr; | |
83 | + int addr_used; | |
84 | + int mask; | |
85 | +}; | |
86 | + | |
87 | /* resolv-file parms from command-line */ | |
88 | struct resolvc { | |
89 | struct resolvc *next; | |
90 | @@ -935,9 +942,9 @@ extern struct daemon { | |
91 | struct auth_zone *auth_zones; | |
92 | struct interface_name *int_names; | |
93 | char *mxtarget; | |
94 | - int addr4_netmask; | |
95 | - int addr6_netmask; | |
96 | - char *lease_file; | |
97 | + struct mysubnet *add_subnet4; | |
98 | + struct mysubnet *add_subnet6; | |
99 | + char *lease_file; | |
100 | char *username, *groupname, *scriptuser; | |
101 | char *luascript; | |
102 | char *authserver, *hostmaster; | |
103 | diff --git a/src/option.c b/src/option.c | |
104 | index ecc2619..746cd11 100644 | |
105 | --- a/src/option.c | |
106 | +++ b/src/option.c | |
107 | @@ -445,7 +445,7 @@ static struct { | |
108 | { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL }, | |
109 | { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL }, | |
110 | { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL }, | |
111 | - { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL }, | |
112 | + { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL }, | |
113 | { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL }, | |
114 | { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL }, | |
115 | { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL }, | |
116 | @@ -722,6 +722,20 @@ static void do_usage(void) | |
117 | ||
118 | #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0) | |
119 | ||
120 | +static char *parse_mysockaddr(char *arg, union mysockaddr *addr) | |
121 | +{ | |
122 | + if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0) | |
123 | + addr->sa.sa_family = AF_INET; | |
124 | +#ifdef HAVE_IPV6 | |
125 | + else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) | |
126 | + addr->sa.sa_family = AF_INET6; | |
127 | +#endif | |
128 | + else | |
129 | + return _("bad address"); | |
130 | + | |
131 | + return NULL; | |
132 | +} | |
133 | + | |
134 | char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags) | |
135 | { | |
136 | int source_port = 0, serv_port = NAMESERVER_PORT; | |
137 | @@ -1585,7 +1599,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma | |
138 | li = match_suffix->next; | |
139 | free(match_suffix->suffix); | |
140 | free(match_suffix); | |
141 | - } | |
142 | + } | |
143 | break; | |
144 | } | |
145 | ||
146 | @@ -1593,10 +1607,45 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma | |
147 | set_option_bool(OPT_CLIENT_SUBNET); | |
148 | if (arg) | |
149 | { | |
150 | + char *err, *end; | |
151 | comma = split(arg); | |
152 | - if (!atoi_check(arg, &daemon->addr4_netmask) || | |
153 | - (comma && !atoi_check(comma, &daemon->addr6_netmask))) | |
154 | - ret_err(gen_err); | |
155 | + | |
156 | + struct mysubnet* new = opt_malloc(sizeof(struct mysubnet)); | |
157 | + if ((end = split_chr(arg, '/'))) | |
158 | + { | |
159 | + /* has subnet+len */ | |
160 | + err = parse_mysockaddr(arg, &new->addr); | |
161 | + if (err) | |
162 | + ret_err(err); | |
163 | + if (!atoi_check(end, &new->mask)) | |
164 | + ret_err(gen_err); | |
165 | + new->addr_used = 1; | |
166 | + } | |
167 | + else if (!atoi_check(arg, &new->mask)) | |
168 | + ret_err(gen_err); | |
169 | + | |
170 | + daemon->add_subnet4 = new; | |
171 | + | |
172 | + new = opt_malloc(sizeof(struct mysubnet)); | |
173 | + if (comma) | |
174 | + { | |
175 | + if ((end = split_chr(comma, '/'))) | |
176 | + { | |
177 | + /* has subnet+len */ | |
178 | + err = parse_mysockaddr(comma, &new->addr); | |
179 | + if (err) | |
180 | + ret_err(err); | |
181 | + if (!atoi_check(end, &new->mask)) | |
182 | + ret_err(gen_err); | |
183 | + new->addr_used = 1; | |
184 | + } | |
185 | + else | |
186 | + { | |
187 | + if (!atoi_check(comma, &new->mask)) | |
188 | + ret_err(gen_err); | |
189 | + } | |
190 | + } | |
191 | + daemon->add_subnet6 = new; | |
192 | } | |
193 | break; | |
194 | ||
195 | diff --git a/src/rfc1035.c b/src/rfc1035.c | |
196 | index 29e9e65..6a51b30 100644 | |
197 | --- a/src/rfc1035.c | |
198 | +++ b/src/rfc1035.c | |
199 | @@ -629,26 +629,47 @@ struct subnet_opt { | |
200 | #endif | |
201 | }; | |
202 | ||
203 | +static void *get_addrp(union mysockaddr *addr, const short family) | |
204 | +{ | |
205 | +#ifdef HAVE_IPV6 | |
206 | + if (family == AF_INET6) | |
207 | + return &addr->in6.sin6_addr; | |
208 | +#endif | |
209 | + | |
210 | + return &addr->in.sin_addr; | |
211 | +} | |
212 | + | |
213 | static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source) | |
214 | { | |
215 | /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */ | |
216 | ||
217 | int len; | |
218 | void *addrp; | |
219 | + int sa_family = source->sa.sa_family; | |
220 | ||
221 | #ifdef HAVE_IPV6 | |
222 | if (source->sa.sa_family == AF_INET6) | |
223 | { | |
224 | - opt->family = htons(2); | |
225 | - opt->source_netmask = daemon->addr6_netmask; | |
226 | - addrp = &source->in6.sin6_addr; | |
227 | + opt->source_netmask = daemon->add_subnet6->mask; | |
228 | + if (daemon->add_subnet6->addr_used) | |
229 | + { | |
230 | + sa_family = daemon->add_subnet6->addr.sa.sa_family; | |
231 | + addrp = get_addrp(&daemon->add_subnet6->addr, sa_family); | |
232 | + } | |
233 | + else | |
234 | + addrp = &source->in6.sin6_addr; | |
235 | } | |
236 | else | |
237 | #endif | |
238 | { | |
239 | - opt->family = htons(1); | |
240 | - opt->source_netmask = daemon->addr4_netmask; | |
241 | - addrp = &source->in.sin_addr; | |
242 | + opt->source_netmask = daemon->add_subnet4->mask; | |
243 | + if (daemon->add_subnet4->addr_used) | |
244 | + { | |
245 | + sa_family = daemon->add_subnet4->addr.sa.sa_family; | |
246 | + addrp = get_addrp(&daemon->add_subnet4->addr, sa_family); | |
247 | + } | |
248 | + else | |
249 | + addrp = &source->in.sin_addr; | |
250 | } | |
251 | ||
252 | opt->scope_netmask = 0; | |
253 | @@ -656,6 +677,11 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source) | |
254 | ||
255 | if (opt->source_netmask != 0) | |
256 | { | |
257 | +#ifdef HAVE_IPV6 | |
258 | + opt->family = htons(sa_family == AF_INET6 ? 2 : 1); | |
259 | +#else | |
260 | + opt->family = htons(1); | |
261 | +#endif | |
262 | len = ((opt->source_netmask - 1) >> 3) + 1; | |
263 | memcpy(opt->addr, addrp, len); | |
264 | if (opt->source_netmask & 7) | |
265 | @@ -2335,4 +2361,3 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, | |
266 | ||
267 | return len; | |
268 | } | |
269 | - | |
270 | -- | |
271 | 1.7.10.4 |