]> git.ipfire.org Git - ipfire-2.x.git/blame - 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
CommitLineData
f831e573
MF
1From a7369bef8abd241c3d85633fa9c870943f091e76 Mon Sep 17 00:00:00 2001
2From: Ed Bardsley <ebardsley@google.com>
3Date: Wed, 5 Aug 2015 21:17:18 +0100
4Subject: [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
14diff --git a/CHANGELOG b/CHANGELOG
15index 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
29diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
30index 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.
72diff --git a/src/dnsmasq.h b/src/dnsmasq.h
73index 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;
103diff --git a/src/option.c b/src/option.c
104index 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
195diff --git a/src/rfc1035.c b/src/rfc1035.c
196index 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--
2711.7.10.4