Home | History | Annotate | Line # | Download | only in ipset
      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  */
     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
     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
     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
     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
    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 	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
    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 				break;
    212 			}
    213 		}
    214 	}
    215 }
    216 
    217 static int
    218 ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
    219 	struct ub_packed_rrset_key *rrset, const char *qname, int qlen,
    220 	const char *setname, int af)
    221 {
    222 	char dname[LDNS_MAX_DOMAINLEN*4+16];
    223 	const char *ds, *qs;
    224 	int dlen, plen;
    225 
    226 	struct config_strlist *p;
    227 	struct packed_rrset_data *d;
    228 
    229 	dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, sizeof(dname));
    230 	if (dlen == 0 || dlen >= (int)sizeof(dname)) {
    231 		log_err("bad domain name");
    232 		return -1;
    233 	}
    234 	if (dname[dlen - 1] == '.') {
    235 		dlen--;
    236 	}
    237 	if (qname[qlen - 1] == '.') {
    238 		qlen--;
    239 	}
    240 
    241 	for (p = env->cfg->local_zones_ipset; p; p = p->next) {
    242 		ds = NULL;
    243 		qs = NULL;
    244 		plen = strlen(p->str);
    245 		if (p->str[plen - 1] == '.') {
    246 			plen--;
    247 		}
    248 
    249 		if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) {
    250 			ds = dname + (dlen - plen);
    251 		}
    252 		if (qlen == plen || (qlen > plen && qname[qlen - plen - 1] == '.' )) {
    253 			qs = qname + (qlen - plen);
    254 		}
    255 		if ((ds && strncasecmp(p->str, ds, plen) == 0)
    256 			|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
    257 			d = (struct packed_rrset_data*)rrset->entry.data;
    258 			ipset_add_rrset_data(ie, d, setname, af, dname);
    259 			break;
    260 		}
    261 	}
    262 	return 0;
    263 }
    264 
    265 static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
    266 	struct query_info qinfo, struct ipset_env *ie)
    267 {
    268 	size_t i;
    269 	const char *setname;
    270 	struct ub_packed_rrset_key *rrset;
    271 	int af;
    272 	char qname[LDNS_MAX_DOMAINLEN*4+16];
    273 	int qlen;
    274 
    275 #ifdef HAVE_NET_PFVAR_H
    276 #else
    277 	if (!ie->dev) {
    278 		/* retry to create mnl socket */
    279 		ie->dev = open_filter();
    280 		if (!ie->dev) {
    281 			log_warn("ipset open_filter failed");
    282 			return -1;
    283 		}
    284 	}
    285 #endif
    286 
    287 	qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
    288 		qname, sizeof(qname));
    289 	if(qlen == 0 || qlen >= (int)sizeof(qname)) {
    290 		log_err("bad domain name");
    291 		return -1;
    292 	}
    293 
    294 	for(i = 0; i < return_msg->rep->rrset_count; i++) {
    295 		setname = NULL;
    296 		rrset = return_msg->rep->rrsets[i];
    297 		if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A &&
    298 			ie->v4_enabled == 1) {
    299 			af = AF_INET;
    300 			setname = ie->name_v4;
    301 		} else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA &&
    302 			ie->v6_enabled == 1) {
    303 			af = AF_INET6;
    304 			setname = ie->name_v6;
    305 		}
    306 
    307 		if (setname) {
    308 			if(ipset_check_zones_for_rrset(env, ie, rrset, qname,
    309 				qlen, setname, af) == -1)
    310 				return -1;
    311 		}
    312 	}
    313 
    314 	return 0;
    315 }
    316 
    317 int ipset_startup(struct module_env* env, int id) {
    318 	struct ipset_env *ipset_env;
    319 
    320 	ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
    321 	if (!ipset_env) {
    322 		log_err("malloc failure");
    323 		return 0;
    324 	}
    325 
    326 	env->modinfo[id] = (void *)ipset_env;
    327 
    328 #ifdef HAVE_NET_PFVAR_H
    329 	ipset_env->dev = open_filter();
    330 	if (!ipset_env->dev) {
    331 		log_err("ipset open_filter failed");
    332 		return 0;
    333 	}
    334 #else
    335 	ipset_env->dev = NULL;
    336 #endif
    337 	return 1;
    338 }
    339 
    340 void ipset_destartup(struct module_env* env, int id) {
    341 	filter_dev dev;
    342 	struct ipset_env *ipset_env;
    343 
    344 	if (!env || !env->modinfo[id]) {
    345 		return;
    346 	}
    347 	ipset_env = (struct ipset_env*)env->modinfo[id];
    348 
    349 	dev = (filter_dev)ipset_env->dev;
    350 	if (dev) {
    351 #if HAVE_NET_PFVAR_H
    352 		close(dev);
    353 #else
    354 		mnl_socket_close(dev);
    355 #endif
    356 		ipset_env->dev = NULL;
    357 	}
    358 
    359 	free(ipset_env);
    360 	env->modinfo[id] = NULL;
    361 }
    362 
    363 int ipset_init(struct module_env* env, int id) {
    364 	struct ipset_env *ipset_env = env->modinfo[id];
    365 
    366 	ipset_env->name_v4 = env->cfg->ipset_name_v4;
    367 	ipset_env->name_v6 = env->cfg->ipset_name_v6;
    368 #ifndef HAVE_NET_PFVAR_H
    369 	if (ipset_env->name_v4 && strlen(ipset_env->name_v4) >= IPSET_MAXNAMELEN) {
    370 		log_err("ipset: name-v4 exceeds IPSET_MAXNAMELEN (%d)", IPSET_MAXNAMELEN);
    371 		return 0;
    372 	}
    373 	if (ipset_env->name_v6 && strlen(ipset_env->name_v6) >= IPSET_MAXNAMELEN) {
    374 		log_err("ipset: name-v6 exceeds IPSET_MAXNAMELEN (%d)", IPSET_MAXNAMELEN);
    375 		return 0;
    376 	}
    377 #endif
    378 
    379 	ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1;
    380 	ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1;
    381 
    382 	if ((ipset_env->v4_enabled < 1) && (ipset_env->v6_enabled < 1)) {
    383 		log_err("ipset: set name no configuration?");
    384 		return 0;
    385 	}
    386 
    387 	return 1;
    388 }
    389 
    390 void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) {
    391 	/* nothing */
    392 }
    393 
    394 static int ipset_new(struct module_qstate* qstate, int id) {
    395 	struct ipset_qstate *iq = (struct ipset_qstate *)regional_alloc(
    396 		qstate->region, sizeof(struct ipset_qstate));
    397 	qstate->minfo[id] = iq;
    398 	if (!iq) {
    399 		return 0;
    400 	}
    401 
    402 	memset(iq, 0, sizeof(*iq));
    403 	/* initialise it */
    404 	/* TODO */
    405 
    406 	return 1;
    407 }
    408 
    409 void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
    410 	struct outbound_entry *outbound) {
    411 	struct ipset_env *ie = (struct ipset_env *)qstate->env->modinfo[id];
    412 	struct ipset_qstate *iq = (struct ipset_qstate *)qstate->minfo[id];
    413 	verbose(VERB_QUERY, "ipset[module %d] operate: extstate:%s event:%s",
    414 		id, strextstate(qstate->ext_state[id]), strmodulevent(event));
    415 	if (iq) {
    416 		log_query_info(VERB_QUERY, "ipset operate: query", &qstate->qinfo);
    417 	}
    418 
    419 	/* perform ipset state machine */
    420 	if ((event == module_event_new || event == module_event_pass) && !iq) {
    421 		if (!ipset_new(qstate, id)) {
    422 			(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
    423 			return;
    424 		}
    425 		iq = (struct ipset_qstate*)qstate->minfo[id];
    426 	}
    427 
    428 	if (iq && (event == module_event_pass || event == module_event_new)) {
    429 		qstate->ext_state[id] = module_wait_module;
    430 		return;
    431 	}
    432 
    433 	if (iq && (event == module_event_moddone)) {
    434 		if (qstate->return_msg && qstate->return_msg->rep) {
    435 			ipset_update(qstate->env, qstate->return_msg, qstate->qinfo, ie);
    436 		}
    437 		qstate->ext_state[id] = module_finished;
    438 		return;
    439 	}
    440 
    441 	if (iq && outbound) {
    442 		/* ipset does not need to process responses at this time
    443 		 * ignore it.
    444 		ipset_process_response(qstate, iq, ie, id, outbound, event);
    445 		*/
    446 		return;
    447 	}
    448 
    449 	if (event == module_event_error) {
    450 		verbose(VERB_ALGO, "got called with event error, giving up");
    451 		(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
    452 		return;
    453 	}
    454 
    455 	if (!iq && (event == module_event_moddone)) {
    456 		/* during priming, module done but we never started */
    457 		qstate->ext_state[id] = module_finished;
    458 		return;
    459 	}
    460 
    461 	log_err("bad event for ipset");
    462 	(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
    463 }
    464 
    465 void ipset_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
    466 	int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) {
    467 	/* ipset does not use subordinate requests at this time */
    468 	verbose(VERB_ALGO, "ipset inform_super was called");
    469 }
    470 
    471 void ipset_clear(struct module_qstate *qstate, int id) {
    472 	struct cachedb_qstate *iq;
    473 	if (!qstate) {
    474 		return;
    475 	}
    476 	iq = (struct cachedb_qstate *)qstate->minfo[id];
    477 	if (iq) {
    478 		/* free contents of iq */
    479 		/* TODO */
    480 	}
    481 	qstate->minfo[id] = NULL;
    482 }
    483 
    484 size_t ipset_get_mem(struct module_env *env, int id) {
    485 	struct ipset_env *ie = (struct ipset_env *)env->modinfo[id];
    486 	if (!ie) {
    487 		return 0;
    488 	}
    489 	return sizeof(*ie);
    490 }
    491 
    492 /**
    493  * The ipset function block
    494  */
    495 static struct module_func_block ipset_block = {
    496 	"ipset",
    497 	&ipset_startup, &ipset_destartup, &ipset_init, &ipset_deinit,
    498 	&ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem
    499 };
    500 
    501 struct module_func_block * ipset_get_funcblock(void) {
    502 	return &ipset_block;
    503 }
    504 
    505