[Dnsmasq-discuss] [PATCH] auth-zone: allow to exclude ip addresses from answer

Simon Kelley simon at thekelleys.org.uk
Sun Jul 24 14:16:48 BST 2016


Patch applied, with a couple of trivial style changes.

Many thanks, looks useful.



Cheers,

Simon.

On 01/06/16 17:07, Mathias Kresin wrote:
> It can be used, to ensure that answers contain only global routeable IP
> addresses (by excluding loopback, RFC1918 and ULA addresses).
> 
> Signed-off-by: Mathias Kresin <dev at kresin.me>
> 
> ---
> 
> This feature was discussed > 1Y ago [1] but never implemented. It is supposed to work
> exactly as described in the the linked e-mail thread.
> 
> [1] http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2015q1/009122.html.
> 
>  man/dnsmasq.8 |  6 +++++-
>  src/auth.c    | 43 ++++++++++++++++++++++++++++++-------------
>  src/dnsmasq.h |  1 +
>  src/option.c  | 22 ++++++++++++++++++++--
>  4 files changed, 56 insertions(+), 16 deletions(-)
> 
> diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
> index 0521534..8a22179 100644
> --- a/man/dnsmasq.8
> +++ b/man/dnsmasq.8
> @@ -739,7 +739,7 @@ a return code of SERVFAIL. Note that
>  setting this may affect DNS behaviour in bad ways, it is not an
>  extra-logging flag and should not be set in production.
>  .TP
> -.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
> +.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....][,exclude:<subnet>[/<prefix length>]].....]
>  Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
>  will be served. If subnet(s) are given, A and AAAA records must be in one of the
>  specified subnets.
> @@ -756,6 +756,10 @@ appear in the zone, but RFC1918 IPv4 addresses which should not.
>  Interface-name and address-literal subnet specifications may be used
>  freely in the same --auth-zone declaration.
>  
> +It's possible to exclude certain IP addresses from responses. It can be
> +used, to make sure that answers contain only global routeable IP
> +addresses (by excluding loopback, RFC1918 and ULA addresses).
> +
>  The subnet(s) are also used to define in-addr.arpa and
>  ip6.arpa domains which are served for reverse-DNS queries. If not
>  specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
> diff --git a/src/auth.c b/src/auth.c
> index 198572d..6c72995 100644
> --- a/src/auth.c
> +++ b/src/auth.c
> @@ -18,36 +18,53 @@
>  
>  #ifdef HAVE_AUTH
>  
> -static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
> +static struct addrlist *find_addrlist(struct addrlist *list, int flag, struct all_addr *addr_u)
>  {
> -  struct addrlist *subnet;
> -
> -  for (subnet = zone->subnet; subnet; subnet = subnet->next)
> -    {
> -      if (!(subnet->flags & ADDRLIST_IPV6))
> +  do {
> +      if (!(list->flags & ADDRLIST_IPV6))
>  	{
>  	  struct in_addr netmask, addr = addr_u->addr.addr4;
>  
>  	  if (!(flag & F_IPV4))
>  	    continue;
>  	  
> -	  netmask.s_addr = htonl(~(in_addr_t)0 << (32 - subnet->prefixlen));
> +	  netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
>  	  
> -	  if  (is_same_net(addr, subnet->addr.addr.addr4, netmask))
> -	    return subnet;
> +	  if  (is_same_net(addr, list->addr.addr.addr4, netmask))
> +	    return list;
>  	}
>  #ifdef HAVE_IPV6
> -      else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
> -	return subnet;
> +      else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen))
> +	return list;
>  #endif
>  
> -    }
> +    } while ((list = list->next));
> +
>    return NULL;
>  }
>  
> +static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
> +{
> +  if (!zone->subnet)
> +    return NULL;
> +
> +  return find_addrlist(zone->subnet, flag, addr_u);
> +}
> +
> +static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct all_addr *addr_u)
> +{
> +  if (!zone->exclude)
> +    return NULL;
> +
> +  return find_addrlist(zone->exclude, flag, addr_u);
> +}
> +
>  static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
>  {
> -  /* No zones specified, no filter */
> +  if (find_exclude(zone, flag, addr_u) != NULL)
> +    return 0;
> +
> +  /* No subnets specified, no filter */
>    if (!zone->subnet)
>      return 1;
>    
> diff --giauth-zone: allow to exclude ip addresses from answert a/src/dnsmasq.h b/src/dnsmasq.h
> index 1896a64..c35f687 100644
> --- a/src/dnsmasq.h
> +++ b/src/dnsmasq.h
> @@ -340,6 +340,7 @@ struct auth_zone {
>      struct auth_name_list *next;
>    } *interface_names;
>    struct addrlist *subnet;
> +  struct addrlist *exclude;
>    struct auth_zone *next;
>  };
>  
> diff --git a/src/option.c b/src/option.c
> index d8c57d6..dd831c0 100644
> --- a/src/option.c
> +++ b/src/option.c
> @@ -1906,6 +1906,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
>  	new = opt_malloc(sizeof(struct auth_zone));
>  	new->domain = opt_string_alloc(arg);
>  	new->subnet = NULL;
> +	new->exclude = NULL;
>  	new->interface_names = NULL;
>  	new->next = daemon->auth_zones;
>  	daemon->auth_zones = new;
> @@ -1913,8 +1914,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
>  	while ((arg = comma))
>  	  {
>  	    int prefixlen = 0;
> +	    int is_exclude = 0;
>  	    char *prefix;
>  	    struct addrlist *subnet =  NULL;
> +	    struct addrlist *exclude = NULL;
>  	    struct all_addr addr;
>  
>  	    comma = split(arg);
> @@ -1923,6 +1926,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
>  	    if (prefix && !atoi_check(prefix, &prefixlen))
>  	      ret_err(gen_err);
>  	    
> +	    if (strstr(arg, "exclude:") == arg)
> +	      {
> +		    is_exclude = 1;
> +		    arg = arg+8;
> +	      }
> +
>  	    if (inet_pton(AF_INET, arg, &addr.addr.addr4))
>  	      {
>  		subnet = opt_malloc(sizeof(struct addrlist));
> @@ -1960,8 +1969,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
>  	    if (subnet)
>  	      {
>  		subnet->addr = addr;
> -		subnet->next = new->subnet;
> -		new->subnet = subnet;
> +
> +		if (is_exclude)
> +		  {
> +		    subnet->next = new->exclude;
> +		    new->exclude = subnet;
> +		  }
> +		else
> +		  {
> +		    subnet->next = new->subnet;
> +		    new->subnet = subnet;
> +		  }
>  	      }
>  	  }
>  	break;
> 




More information about the Dnsmasq-discuss mailing list