]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/002-enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch
bird: New package
[ipfire-2.x.git] / src / patches / dnsmasq / 002-enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch
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