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 #include <libmnl/libmnl.h> 21 #include <linux/netfilter/nfnetlink.h> 22 #include <linux/netfilter/ipset/ip_set.h> 23 24 #define BUFF_LEN 256 25 26 /** 27 * Return an error 28 * @param qstate: our query state 29 * @param id: module id 30 * @param rcode: error code (DNS errcode). 31 * @return: 0 for use by caller, to make notation easy, like: 32 * return error_response(..). 33 */ 34 static int error_response(struct module_qstate* qstate, int id, int rcode) { 35 verbose(VERB_QUERY, "return error response %s", 36 sldns_lookup_by_id(sldns_rcodes, rcode)? 37 sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??"); 38 qstate->return_rcode = rcode; 39 qstate->return_msg = NULL; 40 qstate->ext_state[id] = module_finished; 41 return 0; 42 } 43 44 static struct mnl_socket * open_mnl_socket() { 45 struct mnl_socket *mnl; 46 47 mnl = mnl_socket_open(NETLINK_NETFILTER); 48 if (!mnl) { 49 log_err("ipset: could not open netfilter."); 50 return NULL; 51 } 52 53 if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) { 54 mnl_socket_close(mnl); 55 log_err("ipset: could not bind netfilter."); 56 return NULL; 57 } 58 return mnl; 59 } 60 61 static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) { 62 struct nlmsghdr *nlh; 63 struct nfgenmsg *nfg; 64 struct nlattr *nested[2]; 65 static char buffer[BUFF_LEN]; 66 67 if (strlen(setname) >= IPSET_MAXNAMELEN) { 68 errno = ENAMETOOLONG; 69 return -1; 70 } 71 if (af != AF_INET && af != AF_INET6) { 72 errno = EAFNOSUPPORT; 73 return -1; 74 } 75 76 nlh = mnl_nlmsg_put_header(buffer); 77 nlh->nlmsg_type = IPSET_CMD_ADD | (NFNL_SUBSYS_IPSET << 8); 78 nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL; 79 80 nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); 81 nfg->nfgen_family = af; 82 nfg->version = NFNETLINK_V0; 83 nfg->res_id = htons(0); 84 85 mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); 86 mnl_attr_put(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname); 87 nested[0] = mnl_attr_nest_start(nlh, IPSET_ATTR_DATA); 88 nested[1] = mnl_attr_nest_start(nlh, IPSET_ATTR_IP); 89 mnl_attr_put(nlh, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) 90 | NLA_F_NET_BYTEORDER, (af == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)), ipaddr); 91 mnl_attr_nest_end(nlh, nested[1]); 92 mnl_attr_nest_end(nlh, nested[0]); 93 94 if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) { 95 return -1; 96 } 97 return 0; 98 } 99 100 static void 101 ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl, 102 struct packed_rrset_data *d, const char* setname, int af, 103 const char* dname) 104 { 105 int ret; 106 size_t j, rr_len, rd_len; 107 uint8_t *rr_data; 108 109 /* to d->count, not d->rrsig_count, because we do not want to add the RRSIGs, only the addresses */ 110 for (j = 0; j < d->count; j++) { 111 rr_len = d->rr_len[j]; 112 rr_data = d->rr_data[j]; 113 114 rd_len = sldns_read_uint16(rr_data); 115 if(af == AF_INET && rd_len != INET_SIZE) 116 continue; 117 if(af == AF_INET6 && rd_len != INET6_SIZE) 118 continue; 119 if (rr_len - 2 >= rd_len) { 120 if(verbosity >= VERB_QUERY) { 121 char ip[128]; 122 if(inet_ntop(af, rr_data+2, ip, (socklen_t)sizeof(ip)) == 0) 123 snprintf(ip, sizeof(ip), "(inet_ntop_error)"); 124 verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname); 125 } 126 ret = add_to_ipset(mnl, setname, rr_data + 2, af); 127 if (ret < 0) { 128 log_err("ipset: could not add %s into %s", dname, setname); 129 130 mnl_socket_close(mnl); 131 ie->mnl = NULL; 132 break; 133 } 134 } 135 } 136 } 137 138 static int 139 ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, 140 struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset, 141 const char *qname, const int qlen, const char *setname, int af) 142 { 143 static char dname[BUFF_LEN]; 144 const char *ds, *qs; 145 int dlen, plen; 146 147 struct config_strlist *p; 148 struct packed_rrset_data *d; 149 150 dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN); 151 if (dlen == 0) { 152 log_err("bad domain name"); 153 return -1; 154 } 155 156 for (p = env->cfg->local_zones_ipset; p; p = p->next) { 157 ds = NULL; 158 qs = NULL; 159 plen = strlen(p->str); 160 161 if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) { 162 ds = dname + (dlen - plen); 163 } 164 if (qlen == plen || (qlen > plen && qname[qlen - plen - 1] == '.' )) { 165 qs = qname + (qlen - plen); 166 } 167 if ((ds && strncasecmp(p->str, ds, plen) == 0) 168 || (qs && strncasecmp(p->str, qs, plen) == 0)) { 169 d = (struct packed_rrset_data*)rrset->entry.data; 170 ipset_add_rrset_data(ie, mnl, d, setname, 171 af, dname); 172 break; 173 } 174 } 175 return 0; 176 } 177 178 static int ipset_update(struct module_env *env, struct dns_msg *return_msg, 179 struct query_info qinfo, struct ipset_env *ie) 180 { 181 struct mnl_socket *mnl; 182 size_t i; 183 const char *setname; 184 struct ub_packed_rrset_key *rrset; 185 int af; 186 static char qname[BUFF_LEN]; 187 int qlen; 188 189 mnl = (struct mnl_socket *)ie->mnl; 190 if (!mnl) { 191 /* retry to create mnl socket */ 192 mnl = open_mnl_socket(); 193 if (!mnl) { 194 return -1; 195 } 196 ie->mnl = mnl; 197 } 198 199 qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len, 200 qname, BUFF_LEN); 201 if(qlen == 0) { 202 log_err("bad domain name"); 203 return -1; 204 } 205 206 for(i = 0; i < return_msg->rep->rrset_count; i++) { 207 setname = NULL; 208 rrset = return_msg->rep->rrsets[i]; 209 if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A && 210 ie->v4_enabled == 1) { 211 af = AF_INET; 212 setname = ie->name_v4; 213 } else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA && 214 ie->v6_enabled == 1) { 215 af = AF_INET6; 216 setname = ie->name_v6; 217 } 218 219 if (setname) { 220 if(ipset_check_zones_for_rrset(env, ie, mnl, rrset, 221 qname, qlen, setname, af) == -1) 222 return -1; 223 } 224 } 225 226 return 0; 227 } 228 229 int ipset_init(struct module_env* env, int id) { 230 struct ipset_env *ipset_env; 231 232 ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env)); 233 if (!ipset_env) { 234 log_err("malloc failure"); 235 return 0; 236 } 237 238 env->modinfo[id] = (void *)ipset_env; 239 240 ipset_env->mnl = NULL; 241 242 ipset_env->name_v4 = env->cfg->ipset_name_v4; 243 ipset_env->name_v6 = env->cfg->ipset_name_v6; 244 245 ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1; 246 ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1; 247 248 if ((ipset_env->v4_enabled < 1) && (ipset_env->v6_enabled < 1)) { 249 log_err("ipset: set name no configuration?"); 250 return 0; 251 } 252 253 return 1; 254 } 255 256 void ipset_deinit(struct module_env *env, int id) { 257 struct mnl_socket *mnl; 258 struct ipset_env *ipset_env; 259 260 if (!env || !env->modinfo[id]) { 261 return; 262 } 263 264 ipset_env = (struct ipset_env *)env->modinfo[id]; 265 266 mnl = (struct mnl_socket *)ipset_env->mnl; 267 if (mnl) { 268 mnl_socket_close(mnl); 269 ipset_env->mnl = NULL; 270 } 271 272 free(ipset_env); 273 env->modinfo[id] = NULL; 274 } 275 276 static int ipset_new(struct module_qstate* qstate, int id) { 277 struct ipset_qstate *iq = (struct ipset_qstate *)regional_alloc( 278 qstate->region, sizeof(struct ipset_qstate)); 279 qstate->minfo[id] = iq; 280 if (!iq) { 281 return 0; 282 } 283 284 memset(iq, 0, sizeof(*iq)); 285 /* initialise it */ 286 /* TODO */ 287 288 return 1; 289 } 290 291 void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id, 292 struct outbound_entry *outbound) { 293 struct ipset_env *ie = (struct ipset_env *)qstate->env->modinfo[id]; 294 struct ipset_qstate *iq = (struct ipset_qstate *)qstate->minfo[id]; 295 verbose(VERB_QUERY, "ipset[module %d] operate: extstate:%s event:%s", 296 id, strextstate(qstate->ext_state[id]), strmodulevent(event)); 297 if (iq) { 298 log_query_info(VERB_QUERY, "ipset operate: query", &qstate->qinfo); 299 } 300 301 /* perform ipset state machine */ 302 if ((event == module_event_new || event == module_event_pass) && !iq) { 303 if (!ipset_new(qstate, id)) { 304 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); 305 return; 306 } 307 iq = (struct ipset_qstate*)qstate->minfo[id]; 308 } 309 310 if (iq && (event == module_event_pass || event == module_event_new)) { 311 qstate->ext_state[id] = module_wait_module; 312 return; 313 } 314 315 if (iq && (event == module_event_moddone)) { 316 if (qstate->return_msg && qstate->return_msg->rep) { 317 ipset_update(qstate->env, qstate->return_msg, qstate->qinfo, ie); 318 } 319 qstate->ext_state[id] = module_finished; 320 return; 321 } 322 323 if (iq && outbound) { 324 /* ipset does not need to process responses at this time 325 * ignore it. 326 ipset_process_response(qstate, iq, ie, id, outbound, event); 327 */ 328 return; 329 } 330 331 if (event == module_event_error) { 332 verbose(VERB_ALGO, "got called with event error, giving up"); 333 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); 334 return; 335 } 336 337 if (!iq && (event == module_event_moddone)) { 338 /* during priming, module done but we never started */ 339 qstate->ext_state[id] = module_finished; 340 return; 341 } 342 343 log_err("bad event for ipset"); 344 (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); 345 } 346 347 void ipset_inform_super(struct module_qstate *ATTR_UNUSED(qstate), 348 int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) { 349 /* ipset does not use subordinate requests at this time */ 350 verbose(VERB_ALGO, "ipset inform_super was called"); 351 } 352 353 void ipset_clear(struct module_qstate *qstate, int id) { 354 struct cachedb_qstate *iq; 355 if (!qstate) { 356 return; 357 } 358 iq = (struct cachedb_qstate *)qstate->minfo[id]; 359 if (iq) { 360 /* free contents of iq */ 361 /* TODO */ 362 } 363 qstate->minfo[id] = NULL; 364 } 365 366 size_t ipset_get_mem(struct module_env *env, int id) { 367 struct ipset_env *ie = (struct ipset_env *)env->modinfo[id]; 368 if (!ie) { 369 return 0; 370 } 371 return sizeof(*ie); 372 } 373 374 /** 375 * The ipset function block 376 */ 377 static struct module_func_block ipset_block = { 378 "ipset", 379 &ipset_init, &ipset_deinit, &ipset_operate, 380 &ipset_inform_super, &ipset_clear, &ipset_get_mem 381 }; 382 383 struct module_func_block * ipset_get_funcblock(void) { 384 return &ipset_block; 385 } 386 387