1 /**
2 * \file
3 * This file implements the ipset module. It can handle packets by putting
4 * the A and AAAA addresses that are configured in unbound.conf as type
5 * ipset (local-zone statements) into a firewall rule IPSet. For firewall
6 * blacklist and whitelist usage.
7 */
8 #include "config.h"
9 #include "ipset/ipset.h"
10 #include "util/regional.h"
11 #include "util/net_help.h"
12 #include "util/config_file.h"
13
14 #include "services/cache/dns.h"
15
16 #include "sldns/sbuffer.h"
17 #include "sldns/wire2str.h"
18 #include "sldns/parseutil.h"
19
20 #ifdef HAVE_NET_PFVAR_H
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
23 #include <netinet/in.h>
24 #include <net/if.h>
25 #include <net/pfvar.h>
26 typedef intptr_t filter_dev;
27 #else
28 #include <libmnl/libmnl.h>
29 #include <linux/netfilter/nfnetlink.h>
30 #include <linux/netfilter/ipset/ip_set.h>
31 typedef struct mnl_socket * filter_dev;
32 #endif
33
34 #define BUFF_LEN 256
35
36 /**
37 * Return an error
38 * @param qstate: our query state
39 * @param id: module id
40 * @param rcode: error code (DNS errcode).
41 * @return: 0 for use by caller, to make notation easy, like:
42 * return error_response(..).
43 */
error_response(struct module_qstate * qstate,int id,int rcode)44 static int error_response(struct module_qstate* qstate, int id, int rcode) {
45 verbose(VERB_QUERY, "return error response %s",
46 sldns_lookup_by_id(sldns_rcodes, rcode)?
47 sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??");
48 qstate->return_rcode = rcode;
49 qstate->return_msg = NULL;
50 qstate->ext_state[id] = module_finished;
51 return 0;
52 }
53
54 #ifdef HAVE_NET_PFVAR_H
open_filter()55 static void * open_filter() {
56 filter_dev dev;
57
58 dev = open("/dev/pf", O_RDWR);
59 if (dev == -1) {
60 log_err("open(\"/dev/pf\") failed: %s", strerror(errno));
61 return NULL;
62 }
63 else
64 return (void *)dev;
65 }
66 #else
open_filter()67 static void * open_filter() {
68 filter_dev dev;
69
70 dev = mnl_socket_open(NETLINK_NETFILTER);
71 if (!dev) {
72 log_err("ipset: could not open netfilter.");
73 return NULL;
74 }
75
76 if (mnl_socket_bind(dev, 0, MNL_SOCKET_AUTOPID) < 0) {
77 mnl_socket_close(dev);
78 log_err("ipset: could not bind netfilter.");
79 return NULL;
80 }
81 return (void *)dev;
82 }
83 #endif
84
85 #ifdef HAVE_NET_PFVAR_H
add_to_ipset(filter_dev dev,const char * setname,const void * ipaddr,int af)86 static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
87 struct pfioc_table io;
88 struct pfr_addr addr;
89 const char *p;
90 int i;
91
92 bzero(&io, sizeof(io));
93 bzero(&addr, sizeof(addr));
94
95 p = strrchr(setname, '/');
96 if (p) {
97 i = p - setname;
98 if (i >= PATH_MAX) {
99 errno = ENAMETOOLONG;
100 return -1;
101 }
102 memcpy(io.pfrio_table.pfrt_anchor, setname, i);
103 if (i < PATH_MAX)
104 io.pfrio_table.pfrt_anchor[i] = '\0';
105 p++;
106 }
107 else
108 p = setname;
109
110 if (strlen(p) >= PF_TABLE_NAME_SIZE) {
111 errno = ENAMETOOLONG;
112 return -1;
113 }
114 strlcpy(io.pfrio_table.pfrt_name, p, PF_TABLE_NAME_SIZE);
115
116 io.pfrio_buffer = &addr;
117 io.pfrio_size = 1;
118 io.pfrio_esize = sizeof(addr);
119
120 switch (af) {
121 case AF_INET:
122 addr.pfra_ip4addr = *(struct in_addr *)ipaddr;
123 addr.pfra_net = 32;
124 break;
125 case AF_INET6:
126 addr.pfra_ip6addr = *(struct in6_addr *)ipaddr;
127 addr.pfra_net = 128;
128 break;
129 default:
130 errno = EAFNOSUPPORT;
131 return -1;
132 }
133 addr.pfra_af = af;
134
135 if (ioctl(dev, DIOCRADDADDRS, &io) == -1) {
136 log_err("ioctl failed: %s", strerror(errno));
137 return -1;
138 }
139 return 0;
140 }
141 #else
add_to_ipset(filter_dev dev,const char * setname,const void * ipaddr,int af)142 static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
143 struct nlmsghdr *nlh;
144 struct nfgenmsg *nfg;
145 struct nlattr *nested[2];
146 static char buffer[BUFF_LEN];
147
148 if (strlen(setname) >= IPSET_MAXNAMELEN) {
149 errno = ENAMETOOLONG;
150 return -1;
151 }
152 if (af != AF_INET && af != AF_INET6) {
153 errno = EAFNOSUPPORT;
154 return -1;
155 }
156
157 nlh = mnl_nlmsg_put_header(buffer);
158 nlh->nlmsg_type = IPSET_CMD_ADD | (NFNL_SUBSYS_IPSET << 8);
159 nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL;
160
161 nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
162 nfg->nfgen_family = af;
163 nfg->version = NFNETLINK_V0;
164 nfg->res_id = htons(0);
165
166 mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
167 mnl_attr_put(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
168 nested[0] = mnl_attr_nest_start(nlh, IPSET_ATTR_DATA);
169 nested[1] = mnl_attr_nest_start(nlh, IPSET_ATTR_IP);
170 mnl_attr_put(nlh, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6)
171 | NLA_F_NET_BYTEORDER, (af == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)), ipaddr);
172 mnl_attr_nest_end(nlh, nested[1]);
173 mnl_attr_nest_end(nlh, nested[0]);
174
175 if (mnl_socket_sendto(dev, nlh, nlh->nlmsg_len) < 0) {
176 return -1;
177 }
178 return 0;
179 }
180 #endif
181
182 static void
ipset_add_rrset_data(struct ipset_env * ie,struct packed_rrset_data * d,const char * setname,int af,const char * dname)183 ipset_add_rrset_data(struct ipset_env *ie,
184 struct packed_rrset_data *d, const char* setname, int af,
185 const char* dname)
186 {
187 int ret;
188 size_t j, rr_len, rd_len;
189 uint8_t *rr_data;
190
191 /* to d->count, not d->rrsig_count, because we do not want to add the RRSIGs, only the addresses */
192 for (j = 0; j < d->count; j++) {
193 rr_len = d->rr_len[j];
194 rr_data = d->rr_data[j];
195
196 rd_len = sldns_read_uint16(rr_data);
197 if(af == AF_INET && rd_len != INET_SIZE)
198 continue;
199 if(af == AF_INET6 && rd_len != INET6_SIZE)
200 continue;
201 if (rr_len - 2 >= rd_len) {
202 if(verbosity >= VERB_QUERY) {
203 char ip[128];
204 if(inet_ntop(af, rr_data+2, ip, (socklen_t)sizeof(ip)) == 0)
205 snprintf(ip, sizeof(ip), "(inet_ntop_error)");
206 verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname);
207 }
208 ret = add_to_ipset((filter_dev)ie->dev, setname, rr_data + 2, af);
209 if (ret < 0) {
210 log_err("ipset: could not add %s into %s", dname, setname);
211
212 #if HAVE_NET_PFVAR_H
213 /* don't close as we might not be able to open again due to dropped privs */
214 #else
215 mnl_socket_close((filter_dev)ie->dev);
216 ie->dev = NULL;
217 #endif
218 break;
219 }
220 }
221 }
222 }
223
224 static int
ipset_check_zones_for_rrset(struct module_env * env,struct ipset_env * ie,struct ub_packed_rrset_key * rrset,const char * qname,int qlen,const char * setname,int af)225 ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
226 struct ub_packed_rrset_key *rrset, const char *qname, int qlen,
227 const char *setname, int af)
228 {
229 static char dname[BUFF_LEN];
230 const char *ds, *qs;
231 int dlen, plen;
232
233 struct config_strlist *p;
234 struct packed_rrset_data *d;
235
236 dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN);
237 if (dlen == 0) {
238 log_err("bad domain name");
239 return -1;
240 }
241 if (dname[dlen - 1] == '.') {
242 dlen--;
243 }
244 if (qname[qlen - 1] == '.') {
245 qlen--;
246 }
247
248 for (p = env->cfg->local_zones_ipset; p; p = p->next) {
249 ds = NULL;
250 qs = NULL;
251 plen = strlen(p->str);
252 if (p->str[plen - 1] == '.') {
253 plen--;
254 }
255
256 if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) {
257 ds = dname + (dlen - plen);
258 }
259 if (qlen == plen || (qlen > plen && qname[qlen - plen - 1] == '.' )) {
260 qs = qname + (qlen - plen);
261 }
262 if ((ds && strncasecmp(p->str, ds, plen) == 0)
263 || (qs && strncasecmp(p->str, qs, plen) == 0)) {
264 d = (struct packed_rrset_data*)rrset->entry.data;
265 ipset_add_rrset_data(ie, d, setname, af, dname);
266 break;
267 }
268 }
269 return 0;
270 }
271
ipset_update(struct module_env * env,struct dns_msg * return_msg,struct query_info qinfo,struct ipset_env * ie)272 static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
273 struct query_info qinfo, struct ipset_env *ie)
274 {
275 size_t i;
276 const char *setname;
277 struct ub_packed_rrset_key *rrset;
278 int af;
279 static char qname[BUFF_LEN];
280 int qlen;
281
282 #ifdef HAVE_NET_PFVAR_H
283 #else
284 if (!ie->dev) {
285 /* retry to create mnl socket */
286 ie->dev = open_filter();
287 if (!ie->dev) {
288 log_warn("ipset open_filter failed");
289 return -1;
290 }
291 }
292 #endif
293
294 qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
295 qname, BUFF_LEN);
296 if(qlen == 0) {
297 log_err("bad domain name");
298 return -1;
299 }
300
301 for(i = 0; i < return_msg->rep->rrset_count; i++) {
302 setname = NULL;
303 rrset = return_msg->rep->rrsets[i];
304 if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A &&
305 ie->v4_enabled == 1) {
306 af = AF_INET;
307 setname = ie->name_v4;
308 } else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA &&
309 ie->v6_enabled == 1) {
310 af = AF_INET6;
311 setname = ie->name_v6;
312 }
313
314 if (setname) {
315 if(ipset_check_zones_for_rrset(env, ie, rrset, qname,
316 qlen, setname, af) == -1)
317 return -1;
318 }
319 }
320
321 return 0;
322 }
323
ipset_startup(struct module_env * env,int id)324 int ipset_startup(struct module_env* env, int id) {
325 struct ipset_env *ipset_env;
326
327 ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
328 if (!ipset_env) {
329 log_err("malloc failure");
330 return 0;
331 }
332
333 env->modinfo[id] = (void *)ipset_env;
334
335 #ifdef HAVE_NET_PFVAR_H
336 ipset_env->dev = open_filter();
337 if (!ipset_env->dev) {
338 log_err("ipset open_filter failed");
339 return 0;
340 }
341 #else
342 ipset_env->dev = NULL;
343 #endif
344 return 1;
345 }
346
ipset_destartup(struct module_env * env,int id)347 void ipset_destartup(struct module_env* env, int id) {
348 filter_dev dev;
349 struct ipset_env *ipset_env;
350
351 if (!env || !env->modinfo[id]) {
352 return;
353 }
354 ipset_env = (struct ipset_env*)env->modinfo[id];
355
356 dev = (filter_dev)ipset_env->dev;
357 if (dev) {
358 #if HAVE_NET_PFVAR_H
359 close(dev);
360 #else
361 mnl_socket_close(dev);
362 #endif
363 ipset_env->dev = NULL;
364 }
365
366 free(ipset_env);
367 env->modinfo[id] = NULL;
368 }
369
ipset_init(struct module_env * env,int id)370 int ipset_init(struct module_env* env, int id) {
371 struct ipset_env *ipset_env = env->modinfo[id];
372
373 ipset_env->name_v4 = env->cfg->ipset_name_v4;
374 ipset_env->name_v6 = env->cfg->ipset_name_v6;
375
376 ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1;
377 ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1;
378
379 if ((ipset_env->v4_enabled < 1) && (ipset_env->v6_enabled < 1)) {
380 log_err("ipset: set name no configuration?");
381 return 0;
382 }
383
384 return 1;
385 }
386
ipset_deinit(struct module_env * ATTR_UNUSED (env),int ATTR_UNUSED (id))387 void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) {
388 /* nothing */
389 }
390
ipset_new(struct module_qstate * qstate,int id)391 static int ipset_new(struct module_qstate* qstate, int id) {
392 struct ipset_qstate *iq = (struct ipset_qstate *)regional_alloc(
393 qstate->region, sizeof(struct ipset_qstate));
394 qstate->minfo[id] = iq;
395 if (!iq) {
396 return 0;
397 }
398
399 memset(iq, 0, sizeof(*iq));
400 /* initialise it */
401 /* TODO */
402
403 return 1;
404 }
405
ipset_operate(struct module_qstate * qstate,enum module_ev event,int id,struct outbound_entry * outbound)406 void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
407 struct outbound_entry *outbound) {
408 struct ipset_env *ie = (struct ipset_env *)qstate->env->modinfo[id];
409 struct ipset_qstate *iq = (struct ipset_qstate *)qstate->minfo[id];
410 verbose(VERB_QUERY, "ipset[module %d] operate: extstate:%s event:%s",
411 id, strextstate(qstate->ext_state[id]), strmodulevent(event));
412 if (iq) {
413 log_query_info(VERB_QUERY, "ipset operate: query", &qstate->qinfo);
414 }
415
416 /* perform ipset state machine */
417 if ((event == module_event_new || event == module_event_pass) && !iq) {
418 if (!ipset_new(qstate, id)) {
419 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
420 return;
421 }
422 iq = (struct ipset_qstate*)qstate->minfo[id];
423 }
424
425 if (iq && (event == module_event_pass || event == module_event_new)) {
426 qstate->ext_state[id] = module_wait_module;
427 return;
428 }
429
430 if (iq && (event == module_event_moddone)) {
431 if (qstate->return_msg && qstate->return_msg->rep) {
432 ipset_update(qstate->env, qstate->return_msg, qstate->qinfo, ie);
433 }
434 qstate->ext_state[id] = module_finished;
435 return;
436 }
437
438 if (iq && outbound) {
439 /* ipset does not need to process responses at this time
440 * ignore it.
441 ipset_process_response(qstate, iq, ie, id, outbound, event);
442 */
443 return;
444 }
445
446 if (event == module_event_error) {
447 verbose(VERB_ALGO, "got called with event error, giving up");
448 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
449 return;
450 }
451
452 if (!iq && (event == module_event_moddone)) {
453 /* during priming, module done but we never started */
454 qstate->ext_state[id] = module_finished;
455 return;
456 }
457
458 log_err("bad event for ipset");
459 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
460 }
461
ipset_inform_super(struct module_qstate * ATTR_UNUSED (qstate),int ATTR_UNUSED (id),struct module_qstate * ATTR_UNUSED (super))462 void ipset_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
463 int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) {
464 /* ipset does not use subordinate requests at this time */
465 verbose(VERB_ALGO, "ipset inform_super was called");
466 }
467
ipset_clear(struct module_qstate * qstate,int id)468 void ipset_clear(struct module_qstate *qstate, int id) {
469 struct cachedb_qstate *iq;
470 if (!qstate) {
471 return;
472 }
473 iq = (struct cachedb_qstate *)qstate->minfo[id];
474 if (iq) {
475 /* free contents of iq */
476 /* TODO */
477 }
478 qstate->minfo[id] = NULL;
479 }
480
ipset_get_mem(struct module_env * env,int id)481 size_t ipset_get_mem(struct module_env *env, int id) {
482 struct ipset_env *ie = (struct ipset_env *)env->modinfo[id];
483 if (!ie) {
484 return 0;
485 }
486 return sizeof(*ie);
487 }
488
489 /**
490 * The ipset function block
491 */
492 static struct module_func_block ipset_block = {
493 "ipset",
494 &ipset_startup, &ipset_destartup, &ipset_init, &ipset_deinit,
495 &ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem
496 };
497
ipset_get_funcblock(void)498 struct module_func_block * ipset_get_funcblock(void) {
499 return &ipset_block;
500 }
501
502