/** Insert RR into RPZ's respip_set */
static int
-rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname,
+rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
{
return 0;
}
- if(!netblockdnametoaddr(dname, &addr, &addrlen, &net, &af))
+ if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
return 0;
lock_rw_wrlock(&r->respip_set->lock);
return 0;
}
t = rpz_dname_to_trigger(policydname, policydnamelen);
- verbose(VERB_OPS, "RPZ: found trigger: %s",
- rpz_trigger_to_string(t));
if(t == RPZ_INVALID_TRIGGER) {
free(policydname);
verbose(VERB_ALGO, "RPZ: skipping invalid trigger");
rr_len);
}
else if(t == RPZ_RESPONSE_IP_TRIGGER) {
- rpz_insert_response_ip_trigger(r, policydname,
+ rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
rr_len);
free(policydname);
* @param qclass: qclass
* @param only_exact: if 1 only excact (non wildcard) matches are returned
* @param wr: get write lock for local-zone if 1, read lock if 0
+ * @param zones_keep_lock: if set do not release the r->local_zones lock, this
+ * makes the caller of this function responsible for releasing the lock.
* @return: NULL or local-zone holding rd or wr lock
*/
static struct local_zone*
rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass,
- int only_exact, int wr)
+ int only_exact, int wr, int zones_keep_lock)
{
uint8_t* ce;
size_t ce_len, ce_labs;
} else {
lock_rw_rdlock(&z->lock);
}
- lock_rw_unlock(&r->local_zones->lock);
+ if(!zones_keep_lock) {
+ lock_rw_unlock(&r->local_zones->lock);
+ }
if(exact)
return z;
memmove(wc+2, ce, ce_len);
lock_rw_unlock(&z->lock);
- if(wr) {
- lock_rw_wrlock(&r->local_zones->lock);
- } else {
- lock_rw_rdlock(&r->local_zones->lock);
+ if(!zones_keep_lock) {
+ if(wr) {
+ lock_rw_wrlock(&r->local_zones->lock);
+ } else {
+ lock_rw_rdlock(&r->local_zones->lock);
+ }
}
z = local_zones_find_le(r->local_zones, wc,
ce_len+2, ce_labs+1, qclass, &exact);
} else {
lock_rw_rdlock(&z->lock);
}
- lock_rw_unlock(&r->local_zones->lock);
+ if(!zones_keep_lock) {
+ lock_rw_unlock(&r->local_zones->lock);
+ }
return z;
}
/* no memory recycling for zone deletions ... */
if(prev) prev->next = p->next;
else ld->rrsets = p->next;
-
}
if(d->count > 1) {
if(!local_rrset_remove_rr(d, index))
struct local_zone* z;
int delete_zone = 1;
z = rpz_find_zone(r, dname, dnamelen, rr_class,
- 1 /* only exact */, 1 /* wr lock */);
+ 1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
if(!z) {
verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, "
"RPZ domain not found");
if(delete_zone) {
local_zones_del_zone(r->local_zones, z);
}
+ lock_rw_unlock(&r->local_zones->lock);
return;
}
static void
-rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, enum rpz_action a,
- uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
+rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
+ enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
{
struct resp_addr* node;
struct sockaddr_storage addr;
int net, af;
int delete_respip = 1;
- if(!netblockdnametoaddr(dname, &addr, &addrlen, &net, &af))
+ if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
return;
lock_rw_wrlock(&r->respip_set->lock);
rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
rr_type, rr_class, rdatawl, rdatalen);
} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
- rpz_remove_response_ip_trigger(r, policydname, a, rr_type,
- rdatawl, rdatalen);
+ rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
+ a, rr_type, rdatawl, rdatalen);
}
free(policydname);
}
if(!r->taglist || taglist_intersect(r->taglist,
r->taglistlen, taglist, taglen)) {
z = rpz_find_zone(r, qinfo->qname, qinfo->qname_len,
- qinfo->qclass, 0, 0);
+ qinfo->qclass, 0, 0, 0);
if(z && r->action_override == RPZ_DISABLED_ACTION) {
if(r->log)
log_rpz_apply(z->name,
}
/* RPZ format address dname to network byte order address */
-static int ipdnametoaddr(uint8_t* dname, struct sockaddr_storage* addr,
- socklen_t* addrlen, int* af)
+static int ipdnametoaddr(uint8_t* dname, size_t dnamelen,
+ struct sockaddr_storage* addr, socklen_t* addrlen, int* af)
{
uint8_t* ia;
size_t dnamelabs = dname_count_labels(dname);
uint8_t lablen;
char* e = NULL;
int z = 0;
+ int len = 0;
int i;
*af = AF_INET;
- if(dnamelabs > 6 || dname_has_label(dname, (uint8_t*)"\002zz")) {
+ if(dnamelabs > 6 ||
+ dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) {
*af = AF_INET6;
}
+ len = *dname;
lablen = *dname++;
i = (*af == AF_INET) ? 3 : 15;
if(*af == AF_INET6) {
sa->sin_family = AF_INET;
ia = (uint8_t*)&sa->sin_addr;
}
- while(lablen && i >= 0) {
- char buff[lablen+1];
+ while(lablen && i >= 0 && len <= dnamelen) {
+ char buff[LDNS_MAX_LABELLEN+1];
uint16_t chunk; /* big enough to not overflow on IPv6 hextet */
if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) ||
(*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) {
return 0;
}
if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) {
- /* add one or more 0 labels */
+ /* Add one or more 0 labels. Address is initialised at
+ * 0, so just skip the zero part. */
int zl = 11 - dnamelabs;
if(z || zl < 0)
return 0;
z = 1;
i -= (zl*2);
- memset(ia+(i+1), 0, zl*2);
} else {
memcpy(buff, dname, lablen);
buff[lablen] = '\0';
if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
return 0;
if(*af == AF_INET) {
+ log_assert(i < 4 && i >= 0);
ia[i] = (uint8_t)chunk;
i--;
} else {
+ log_assert(i < 15 && i >= 1);
/* ia in network byte order */
ia[i-1] = (uint8_t)(chunk >> 8);
ia[i] = (uint8_t)(chunk & 0x00FF);
}
dname += lablen;
lablen = *dname++;
+ len += lablen;
}
if(i != -1)
/* input too short */
return 1;
}
-int netblockdnametoaddr(uint8_t* dname, struct sockaddr_storage* addr,
- socklen_t* addrlen, int* net, int* af)
+int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
+ struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af)
{
char buff[3 /* 3 digit netblock */ + 1];
if(*dname > 3)
memcpy(buff, dname+1, *dname);
buff[*dname] = '\0';
*net = atoi(buff);
+ if(*net == 0 && strcmp(buff, "0") != 0)
+ return 0;
dname += *dname;
dname++;
- if(!ipdnametoaddr(dname, addr, addrlen, af))
+ if(!ipdnametoaddr(dname, dnamelen, addr, addrlen, af))
+ return 0;
+ if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32))
return 0;
return 1;
}