]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - edns-subnet/subnet-whitelist.c
Vendor import of Unbound 1.6.2.
[FreeBSD/FreeBSD.git] / edns-subnet / subnet-whitelist.c
1 /*
2  * edns-subnet/subnet-whitelist.c - Hosts we actively try to send subnet option
3  * to.
4  *
5  * Copyright (c) 2013, NLnet Labs. All rights reserved.
6  *
7  * This software is open source.
8  * 
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 
13  * Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  * 
16  * Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  * 
20  * Neither the name of the NLNET LABS nor the names of its contributors may
21  * be used to endorse or promote products derived from this software without
22  * specific prior written permission.
23  * 
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 /**
37  * \file
38  *
39  * Keep track of the white listed servers for subnet option. Based
40  * on acl_list.c|h
41  */
42
43 #include "config.h"
44
45 #ifdef CLIENT_SUBNET /* keeps splint happy */
46 #include "edns-subnet/edns-subnet.h"
47 #include "edns-subnet/subnet-whitelist.h"
48 #include "util/regional.h"
49 #include "util/log.h"
50 #include "util/config_file.h"
51 #include "util/net_help.h"
52 #include "util/storage/dnstree.h"
53
54 struct ednssubnet_upstream* 
55 upstream_create(void)
56 {
57         struct ednssubnet_upstream* upstream = 
58                 (struct ednssubnet_upstream*)calloc(1,
59                 sizeof(struct ednssubnet_upstream));
60         if(!upstream)
61                 return NULL;
62         upstream->region = regional_create();
63         if(!upstream->region) {
64                 upstream_delete(upstream);
65                 return NULL;
66         }
67         return upstream;
68 }
69
70 void 
71 upstream_delete(struct ednssubnet_upstream* upstream)
72 {
73         if(!upstream) 
74                 return;
75         regional_destroy(upstream->region);
76         free(upstream);
77 }
78
79 /** insert new address into upstream structure */
80 static int
81 upstream_insert(struct ednssubnet_upstream* upstream, 
82         struct sockaddr_storage* addr, socklen_t addrlen, int net)
83 {
84         struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc(
85                 upstream->region, sizeof(*node));
86         if(!node)
87                 return 0;
88         if(!addr_tree_insert(&upstream->tree, node, addr, addrlen, net)) {
89                 verbose(VERB_QUERY,
90                         "duplicate send-client-subnet address ignored.");
91         }
92         return 1;
93 }
94
95 /** apply edns-subnet string */
96 static int
97 upstream_str_cfg(struct ednssubnet_upstream* upstream, const char* str)
98 {
99         struct sockaddr_storage addr;
100         int net;
101         socklen_t addrlen;
102         verbose(VERB_ALGO, "send-client-subnet: %s", str);
103         if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
104                 log_err("cannot parse send-client-subnet netblock: %s", str);
105                 return 0;
106         }
107         if(!upstream_insert(upstream, &addr, addrlen, net)) {
108                 log_err("out of memory");
109                 return 0;
110         }
111         return 1;
112 }
113
114 /** read client_subnet config */
115 static int 
116 read_upstream(struct ednssubnet_upstream* upstream, struct config_file* cfg)
117 {
118         struct config_strlist* p;
119         for(p = cfg->client_subnet; p; p = p->next) {
120                 log_assert(p->str);
121                 if(!upstream_str_cfg(upstream, p->str))
122                         return 0;
123         }
124         return 1;
125 }
126
127 int 
128 upstream_apply_cfg(struct ednssubnet_upstream* upstream,
129         struct config_file* cfg)
130 {
131         regional_free_all(upstream->region);
132         addr_tree_init(&upstream->tree);
133         if(!read_upstream(upstream, cfg))
134                 return 0;
135         addr_tree_init_parents(&upstream->tree);
136         return 1;
137 }
138
139 int 
140 upstream_is_whitelisted(struct ednssubnet_upstream* upstream,
141         struct sockaddr_storage* addr, socklen_t addrlen)
142 {
143         return addr_tree_lookup(&upstream->tree, addr, addrlen) != NULL;
144 }
145
146 size_t 
147 upstream_get_mem(struct ednssubnet_upstream* upstream)
148 {
149         if(!upstream) return 0;
150         return sizeof(*upstream) + regional_get_mem(upstream->region);
151 }
152
153 #endif /* CLIENT_SUBNET */