return 1;
}
+/** Insert RR into RPZ's ACL tree */
+static int
+rpz_insert_client_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)
+{
+ /* TODO: remove void casts */
+ (void)r;
+ (void)dnamelen;
+ (void)rrtype;
+ (void)rrclass;
+ (void)ttl;
+ (void)rdata;
+ (void)rdata_len;
+ (void)rr;
+ (void)rr_len;
+
+ if(a == RPZ_DROP_ACTION) {
+ /* insert into r->acl tree */
+ struct sockaddr_storage addr;
+ char str[INET6_ADDRSTRLEN];
+ socklen_t addrlen;
+ int net, af;
+ if(!netblockdnametoaddr(dname, &addr, &addrlen, &net, &af))
+ return 0;
+ /* TODO insert into acl tree */
+#if 0
+ if((inet_ntop(af,
+ (af == AF_INET) ?
+ (void*)&((struct sockaddr_in*)&addr)->sin_addr :
+ (void*)&((struct sockaddr_in6*)&addr)->sin6_addr,
+ str, INET6_ADDRSTRLEN)))
+ log_info("rpz %s/%d\n", str, net);
+#endif
+ } else {
+ verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s",
+ rpz_action_to_string(a));
+ return 0;
+ }
+ return 0;
+}
+
void
rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
rr_len);
}
+ else if(t == RPZ_CLIENT_IP_TRIGGER) {
+ rpz_insert_client_ip_trigger(r, policydname, policydnamelen,
+ a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
+ rr_len);
+ }
else {
free(policydname);
verbose(VERB_ALGO, "RPZ: skipping unusupported trigger: %s",
};
/**
- * RPZ containing policies. Pointed to from corresponding authz-one. Part of a
+ * RPZ containing policies. Pointed to from corresponding auth-zone. Part of a
* linked list to keep configuration order. Iterating or changing the linked
* list requires the rpz_lock from struct auth_zones.
*/
return 1;
}
+int
+dname_has_label(uint8_t* dname, uint8_t* label)
+{
+ uint8_t lablen = *dname++;
+ while(lablen) {
+ if(*label == lablen && memcmp(dname, label+1, lablen) == 0)
+ return 1;
+ dname += lablen;
+ lablen = *dname++;
+ }
+ return 0;
+}
+
int
dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
{
*/
int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr);
+/**
+ * Check if dname contains label
+ * @param dname: dname
+ * @param label: label to be checked for presence in dname
+ * @return: 1 if dname has this label, 0 otherwise
+ */
+int dname_has_label(uint8_t* dname, uint8_t* label);
+
/**
* See if domain name d1 is a strict subdomain of d2.
* That is a subdomain, but not equal.
return 1;
}
+/* RPZ format address dname to network byte order address */
+static int ipdnametoaddr(uint8_t* dname, 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 i;
+ *af = AF_INET;
+ if(dnamelabs > 6 || dname_has_label(dname, (uint8_t*)"\002zz")) {
+ *af = AF_INET6;
+ }
+ lablen = *dname++;
+ i = (*af == AF_INET) ? 3 : 15;
+ if(*af == AF_INET6) {
+ struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
+ *addrlen = (socklen_t)sizeof(struct sockaddr_in6);
+ memset(sa, 0, *addrlen);
+ sa->sin6_family = AF_INET6;
+ ia = (uint8_t*)&sa->sin6_addr;
+ } else { /* ip4 */
+ struct sockaddr_in* sa = (struct sockaddr_in*)addr;
+ *addrlen = (socklen_t)sizeof(struct sockaddr_in);
+ memset(sa, 0, *addrlen);
+ sa->sin_family = AF_INET;
+ ia = (uint8_t*)&sa->sin_addr;
+ }
+ while(lablen && i >= 0) {
+ char buff[lablen+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 */
+ 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';
+ chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16);
+ if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
+ return 0;
+ if(*af == AF_INET) {
+ ia[i] = (uint8_t)chunk;
+ i--;
+ } else {
+ /* ia in network byte order */
+ ia[i-1] = (uint8_t)(chunk >> 8);
+ ia[i] = (uint8_t)(chunk & 0x00FF);
+ i -= 2;
+ }
+ }
+ dname += lablen;
+ lablen = *dname++;
+ }
+ if(i != -1)
+ /* input too short */
+ return 0;
+ return 1;
+}
+
+int netblockdnametoaddr(uint8_t* dname, struct sockaddr_storage* addr,
+ socklen_t* addrlen, int* net, int* af)
+{
+ int e;
+ char buff[3 /* 3 digit netblock */ + 1];
+ if(*dname > 3)
+ /* netblock invalid */
+ return 0;
+ memcpy(buff, dname+1, *dname);
+ buff[(*dname)+1] = '\0';
+ *net = atoi(buff);
+ dname += *dname;
+ dname++;
+ if(!ipdnametoaddr(dname, addr, addrlen, af))
+ return 0;
+ return 1;
+}
+
int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
socklen_t* addrlen, char** auth_name)
{
/** Free memory used for TLS session ticket keys */
void listen_sslctx_delete_ticket_keys(void);
+/**
+ * RPZ format netblock to network byte order address and netblock
+ * @param dname: the dname containing RPZ format netblock
+ * @param addr: where to store sockaddr.
+ * @param addrlen: length of stored sockaddr is returned.
+ * @param af: where to store address family.
+ * @return 0 on error.
+ */
+int netblockdnametoaddr(uint8_t* dname, struct sockaddr_storage* addr,
+ socklen_t* addrlen, int* net, int* af);
#endif /* NET_HELP_H */