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 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 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 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 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 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 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 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 387 void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) { 388 /* nothing */ 389 } 390 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 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 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 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 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 498 struct module_func_block * ipset_get_funcblock(void) { 499 return &ipset_block; 500 } 501 502