]>
Commit | Line | Data |
---|---|---|
bf8378e4 MF |
1 | From 094bfaeb4ff69cae99387bc2ea07ff57632c89f5 Mon Sep 17 00:00:00 2001 |
2 | From: Mathias Kresin <dev@kresin.me> | |
3 | Date: Sun, 24 Jul 2016 14:15:22 +0100 | |
4 | Subject: [PATCH] auth-zone: allow to exclude ip addresses from answer. | |
5 | ||
6 | --- | |
7 | man/dnsmasq.8 | 6 +++++- | |
8 | src/auth.c | 61 ++++++++++++++++++++++++++++++++++++--------------------- | |
9 | src/dnsmasq.h | 1 + | |
10 | src/option.c | 21 ++++++++++++++++++-- | |
11 | 4 files changed, 64 insertions(+), 25 deletions(-) | |
12 | ||
13 | diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 | |
14 | index ac8d921..8910947 100644 | |
15 | --- a/man/dnsmasq.8 | |
16 | +++ b/man/dnsmasq.8 | |
17 | @@ -739,7 +739,7 @@ a return code of SERVFAIL. Note that | |
18 | setting this may affect DNS behaviour in bad ways, it is not an | |
19 | extra-logging flag and should not be set in production. | |
20 | .TP | |
21 | -.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]] | |
22 | +.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....][,exclude:<subnet>[/<prefix length>]].....] | |
23 | Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain | |
24 | will be served. If subnet(s) are given, A and AAAA records must be in one of the | |
25 | specified subnets. | |
26 | @@ -756,6 +756,10 @@ appear in the zone, but RFC1918 IPv4 addresses which should not. | |
27 | Interface-name and address-literal subnet specifications may be used | |
28 | freely in the same --auth-zone declaration. | |
29 | ||
30 | +It's possible to exclude certain IP addresses from responses. It can be | |
31 | +used, to make sure that answers contain only global routeable IP | |
32 | +addresses (by excluding loopback, RFC1918 and ULA addresses). | |
33 | + | |
34 | The subnet(s) are also used to define in-addr.arpa and | |
35 | ip6.arpa domains which are served for reverse-DNS queries. If not | |
36 | specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6. | |
37 | diff --git a/src/auth.c b/src/auth.c | |
38 | index 3c5c37f..f1ca2f5 100644 | |
39 | --- a/src/auth.c | |
40 | +++ b/src/auth.c | |
41 | @@ -18,36 +18,53 @@ | |
42 | ||
43 | #ifdef HAVE_AUTH | |
44 | ||
45 | -static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u) | |
46 | +static struct addrlist *find_addrlist(struct addrlist *list, int flag, struct all_addr *addr_u) | |
47 | { | |
48 | - struct addrlist *subnet; | |
49 | - | |
50 | - for (subnet = zone->subnet; subnet; subnet = subnet->next) | |
51 | - { | |
52 | - if (!(subnet->flags & ADDRLIST_IPV6)) | |
53 | - { | |
54 | - struct in_addr netmask, addr = addr_u->addr.addr4; | |
55 | - | |
56 | - if (!(flag & F_IPV4)) | |
57 | - continue; | |
58 | - | |
59 | - netmask.s_addr = htonl(~(in_addr_t)0 << (32 - subnet->prefixlen)); | |
60 | - | |
61 | - if (is_same_net(addr, subnet->addr.addr.addr4, netmask)) | |
62 | - return subnet; | |
63 | - } | |
64 | + do { | |
65 | + if (!(list->flags & ADDRLIST_IPV6)) | |
66 | + { | |
67 | + struct in_addr netmask, addr = addr_u->addr.addr4; | |
68 | + | |
69 | + if (!(flag & F_IPV4)) | |
70 | + continue; | |
71 | + | |
72 | + netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen)); | |
73 | + | |
74 | + if (is_same_net(addr, list->addr.addr.addr4, netmask)) | |
75 | + return list; | |
76 | + } | |
77 | #ifdef HAVE_IPV6 | |
78 | - else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen)) | |
79 | - return subnet; | |
80 | + else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen)) | |
81 | + return list; | |
82 | #endif | |
83 | - | |
84 | - } | |
85 | + | |
86 | + } while ((list = list->next)); | |
87 | + | |
88 | return NULL; | |
89 | } | |
90 | ||
91 | +static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u) | |
92 | +{ | |
93 | + if (!zone->subnet) | |
94 | + return NULL; | |
95 | + | |
96 | + return find_addrlist(zone->subnet, flag, addr_u); | |
97 | +} | |
98 | + | |
99 | +static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct all_addr *addr_u) | |
100 | +{ | |
101 | + if (!zone->exclude) | |
102 | + return NULL; | |
103 | + | |
104 | + return find_addrlist(zone->exclude, flag, addr_u); | |
105 | +} | |
106 | + | |
107 | static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u) | |
108 | { | |
109 | - /* No zones specified, no filter */ | |
110 | + if (find_exclude(zone, flag, addr_u)) | |
111 | + return 0; | |
112 | + | |
113 | + /* No subnets specified, no filter */ | |
114 | if (!zone->subnet) | |
115 | return 1; | |
116 | ||
117 | diff --git a/src/dnsmasq.h b/src/dnsmasq.h | |
118 | index 2bda5d0..27385a9 100644 | |
119 | --- a/src/dnsmasq.h | |
120 | +++ b/src/dnsmasq.h | |
121 | @@ -340,6 +340,7 @@ struct auth_zone { | |
122 | struct auth_name_list *next; | |
123 | } *interface_names; | |
124 | struct addrlist *subnet; | |
125 | + struct addrlist *exclude; | |
126 | struct auth_zone *next; | |
127 | }; | |
128 | ||
129 | diff --git a/src/option.c b/src/option.c | |
130 | index d8c57d6..6cedef3 100644 | |
131 | --- a/src/option.c | |
132 | +++ b/src/option.c | |
133 | @@ -1906,6 +1906,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma | |
134 | new = opt_malloc(sizeof(struct auth_zone)); | |
135 | new->domain = opt_string_alloc(arg); | |
136 | new->subnet = NULL; | |
137 | + new->exclude = NULL; | |
138 | new->interface_names = NULL; | |
139 | new->next = daemon->auth_zones; | |
140 | daemon->auth_zones = new; | |
141 | @@ -1913,6 +1914,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma | |
142 | while ((arg = comma)) | |
143 | { | |
144 | int prefixlen = 0; | |
145 | + int is_exclude = 0; | |
146 | char *prefix; | |
147 | struct addrlist *subnet = NULL; | |
148 | struct all_addr addr; | |
149 | @@ -1923,6 +1925,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma | |
150 | if (prefix && !atoi_check(prefix, &prefixlen)) | |
151 | ret_err(gen_err); | |
152 | ||
153 | + if (strstr(arg, "exclude:") == arg) | |
154 | + { | |
155 | + is_exclude = 1; | |
156 | + arg = arg+8; | |
157 | + } | |
158 | + | |
159 | if (inet_pton(AF_INET, arg, &addr.addr.addr4)) | |
160 | { | |
161 | subnet = opt_malloc(sizeof(struct addrlist)); | |
162 | @@ -1960,8 +1968,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma | |
163 | if (subnet) | |
164 | { | |
165 | subnet->addr = addr; | |
166 | - subnet->next = new->subnet; | |
167 | - new->subnet = subnet; | |
168 | + | |
169 | + if (is_exclude) | |
170 | + { | |
171 | + subnet->next = new->exclude; | |
172 | + new->exclude = subnet; | |
173 | + } | |
174 | + else | |
175 | + { | |
176 | + subnet->next = new->subnet; | |
177 | + new->subnet = subnet; | |
178 | + } | |
179 | } | |
180 | } | |
181 | break; | |
182 | -- | |
183 | 1.7.10.4 | |
184 |