/** printout a delegation point info */ static int ssl_print_name_dp(SSL* ssl, char* str, uint8_t* nm, uint16_t dclass, struct delegpt* dp) { char buf[257]; struct delegpt_ns* ns; struct delegpt_addr* a; int f = 0; if(str) { /* print header for forward, stub */ char* c = ldns_rr_class2str(dclass); dname_str(nm, buf); if(!ssl_printf(ssl, "%s %s %s: ", buf, c, str)) { free(c); return 0; } free(c); } for(ns = dp->nslist; ns; ns = ns->next) { dname_str(ns->name, buf); if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) return 0; f = 1; } for(a = dp->target_list; a; a = a->next_target) { addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) return 0; f = 1; } return ssl_printf(ssl, "\n"); }
void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, struct sockaddr_storage* addr, socklen_t addrlen) { uint16_t port; const char* family = "unknown_family "; char namebuf[LDNS_MAX_DOMAINLEN+1]; char dest[100]; int af = (int)((struct sockaddr_in*)addr)->sin_family; void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; if(verbosity < v) return; switch(af) { case AF_INET: family=""; break; case AF_INET6: family=""; sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; break; case AF_LOCAL: family="local "; break; default: break; } if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); } dest[sizeof(dest)-1] = 0; port = ntohs(((struct sockaddr_in*)addr)->sin_port); dname_str(zone, namebuf); if(af != AF_INET && af != AF_INET6) verbose(v, "%s <%s> %s%s#%d (addrlen %d)", str, namebuf, family, dest, (int)port, (int)addrlen); else verbose(v, "%s <%s> %s%s#%d", str, namebuf, family, dest, (int)port); }
void log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, uint16_t type, uint16_t dclass) { char buf[LDNS_MAX_DOMAINLEN+1]; char t[12], c[12]; const char *ts, *cs; if(verbosity < v) return; dname_str(name, buf); if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) ts = sldns_rr_descript(type)->_name; else { snprintf(t, sizeof(t), "TYPE%d", (int)type); ts = t; } if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; else { snprintf(c, sizeof(c), "CLASS%d", (int)dclass); cs = c; } log_info("%s %s %s %s", str, buf, ts, cs); }
int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name, size_t namelen, time_t timenow) { int lim, max; struct lruhash_entry* entry; if(!infra_dp_ratelimit) return 1; /* not enabled */ /* find ratelimit */ lim = infra_find_ratelimit(infra, name, namelen); /* find or insert ratedata */ entry = infra_find_ratedata(infra, name, namelen, 1); if(entry) { int premax = infra_rate_max(entry->data, timenow); int* cur = infra_rate_find_second(entry->data, timenow); (*cur)++; max = infra_rate_max(entry->data, timenow); lock_rw_unlock(&entry->lock); if(premax < lim && max >= lim) { char buf[257]; dname_str(name, buf); verbose(VERB_OPS, "ratelimit exceeded %s %d", buf, lim); } return (max < lim); } /* create */ infra_create_ratedata(infra, name, namelen, timenow); return (1 < lim); }
/** * Assemble the rrsets in the anchors, ready for use by validator. * @param anchors: trust anchor storage. * @return: false on error. */ static int anchors_assemble_rrsets(struct val_anchors* anchors) { struct trust_anchor* ta; struct trust_anchor* next; size_t nods, nokey; lock_basic_lock(&anchors->lock); ta=(struct trust_anchor*)rbtree_first(anchors->tree); while((rbnode_type*)ta != RBTREE_NULL) { next = (struct trust_anchor*)rbtree_next(&ta->node); lock_basic_lock(&ta->lock); if(ta->autr || (ta->numDS == 0 && ta->numDNSKEY == 0)) { lock_basic_unlock(&ta->lock); ta = next; /* skip */ continue; } if(!anchors_assemble(ta)) { log_err("out of memory"); lock_basic_unlock(&ta->lock); lock_basic_unlock(&anchors->lock); return 0; } nods = anchors_ds_unsupported(ta); nokey = anchors_dnskey_unsupported(ta); if(nods) { log_nametypeclass(0, "warning: unsupported " "algorithm for trust anchor", ta->name, LDNS_RR_TYPE_DS, ta->dclass); } if(nokey) { log_nametypeclass(0, "warning: unsupported " "algorithm for trust anchor", ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); } if(nods == ta->numDS && nokey == ta->numDNSKEY) { char b[257]; dname_str(ta->name, b); log_warn("trust anchor %s has no supported algorithms," " the anchor is ignored (check if you need to" " upgrade unbound and " #ifdef HAVE_LIBRESSL "libressl" #else "openssl" #endif ")", b); (void)rbtree_delete(anchors->tree, &ta->node); lock_basic_unlock(&ta->lock); if(anchors->dlv_anchor == ta) anchors->dlv_anchor = NULL; anchors_delfunc(&ta->node, NULL); ta = next; continue; } lock_basic_unlock(&ta->lock); ta = next; } lock_basic_unlock(&anchors->lock); return 1; }
/** insert canonname */ static int fill_canon(struct ub_result* res, uint8_t* s) { char buf[255+2]; dname_str(s, buf); res->canonname = strdup(buf); return res->canonname != 0; }
void delegpt_log(enum verbosity_value v, struct delegpt* dp) { char buf[LDNS_MAX_DOMAINLEN+1]; struct delegpt_ns* ns; struct delegpt_addr* a; size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0; if(verbosity < v) return; dname_str(dp->name, buf); if(dp->nslist == NULL && dp->target_list == NULL) { log_info("DelegationPoint<%s>: empty", buf); return; } delegpt_count_ns(dp, &numns, &missing); delegpt_count_addr(dp, &numaddr, &numres, &numavail); log_info("DelegationPoint<%s>: %u names (%u missing), " "%u addrs (%u result, %u avail)%s", buf, (unsigned)numns, (unsigned)missing, (unsigned)numaddr, (unsigned)numres, (unsigned)numavail, (dp->has_parent_side_NS?" parentNS":" cacheNS")); if(verbosity >= VERB_ALGO) { for(ns = dp->nslist; ns; ns = ns->next) { dname_str(ns->name, buf); log_info(" %s %s%s%s%s%s%s%s", buf, (ns->resolved?"*":""), (ns->got4?" A":""), (ns->got6?" AAAA":""), (dp->bogus?" BOGUS":""), (ns->lame?" PARENTSIDE":""), (ns->done_pside4?" PSIDE_A":""), (ns->done_pside6?" PSIDE_AAAA":"")); } for(a = dp->target_list; a; a = a->next_target) { const char* str = " "; if(a->bogus && a->lame) str = " BOGUS ADDR_LAME "; else if(a->bogus) str = " BOGUS "; else if(a->lame) str = " ADDR_LAME "; log_addr(VERB_ALGO, str, &a->addr, a->addrlen); } } }
/** debug printout of neg cache */ static void print_neg_cache(struct val_neg_cache* neg) { char buf[1024]; struct val_neg_zone* z; struct val_neg_data* d; printf("neg_cache print\n"); printf("memuse %d of %d\n", (int)neg->use, (int)neg->max); printf("maxiter %d\n", (int)neg->nsec3_max_iter); printf("%d zones\n", (int)neg->tree.count); RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { dname_str(z->name, buf); printf("%24s", buf); printf(" len=%2.2d labs=%d inuse=%d count=%d tree.count=%d\n", (int)z->len, z->labs, (int)z->in_use, z->count, (int)z->tree.count); } RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { printf("\n"); dname_print(stdout, NULL, z->name); printf(" zone details\n"); printf("len=%2.2d labs=%d inuse=%d count=%d tree.count=%d\n", (int)z->len, z->labs, (int)z->in_use, z->count, (int)z->tree.count); if(z->parent) { printf("parent="); dname_print(stdout, NULL, z->parent->name); printf("\n"); } else { printf("parent=NULL\n"); } RBTREE_FOR(d, struct val_neg_data*, &z->tree) { dname_str(d->name, buf); printf("%24s", buf); printf(" len=%2.2d labs=%d inuse=%d count=%d\n", (int)d->len, d->labs, (int)d->in_use, d->count); } } }
/** print log information for an inform zone query */ static void lz_inform_print(struct local_zone* z, struct query_info* qinfo, struct comm_reply* repinfo) { char ip[128], txt[512]; char zname[LDNS_MAX_DOMAINLEN+1]; uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port); dname_str(z->name, zname); addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip)); snprintf(txt, sizeof(txt), "%s inform %s@%u", zname, ip, (unsigned)port); log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass); }
/** get status of a mesh state */ static void get_mesh_status(struct mesh_area* mesh, struct mesh_state* m, char* buf, size_t len) { enum module_ext_state s = m->s.ext_state[m->s.curmod]; const char *modname = mesh->mods.mod[m->s.curmod]->name; size_t l; if(strcmp(modname, "iterator") == 0 && s == module_wait_reply && m->s.minfo[m->s.curmod]) { /* break into iterator to find out who its waiting for */ struct iter_qstate* qstate = (struct iter_qstate*) m->s.minfo[m->s.curmod]; struct outbound_list* ol = &qstate->outlist; struct outbound_entry* e; snprintf(buf, len, "%s wait for", modname); l = strlen(buf); buf += l; len -= l; if(ol->first == NULL) snprintf(buf, len, " (empty_list)"); for(e = ol->first; e; e = e->next) { snprintf(buf, len, " "); l = strlen(buf); buf += l; len -= l; addr_to_str(&e->qsent->addr, e->qsent->addrlen, buf, len); l = strlen(buf); buf += l; len -= l; } } else if(s == module_wait_subquery) { /* look in subs from mesh state to see what */ char nm[257]; struct mesh_state_ref* sub; snprintf(buf, len, "%s wants", modname); l = strlen(buf); buf += l; len -= l; if(m->sub_set.count == 0) snprintf(buf, len, " (empty_list)"); RBTREE_FOR(sub, struct mesh_state_ref*, &m->sub_set) { char* t = ldns_rr_type2str(sub->s->s.qinfo.qtype); char* c = ldns_rr_class2str(sub->s->s.qinfo.qclass); dname_str(sub->s->s.qinfo.qname, nm); snprintf(buf, len, " %s %s %s", t, c, nm); l = strlen(buf); buf += l; len -= l; free(t); free(c); } } else {
/** insert new hint info into hint structure */ static int hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp, int noprime) { struct iter_hints_stub* node = (struct iter_hints_stub*)malloc( sizeof(struct iter_hints_stub)); if(!node) { delegpt_free_mlc(dp); return 0; } node->dp = dp; node->noprime = (uint8_t)noprime; if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen, dp->namelabs, c)) { char buf[257]; dname_str(dp->name, buf); log_err("second hints for zone %s ignored.", buf); delegpt_free_mlc(dp); free(node); } return 1; }
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm, size_t nmlen, int ATTR_UNUSED(nmlabs)) { /* deep links into the iterator module */ struct delegpt* dp; struct dns_msg* msg; struct regional* region = worker->scratchpad; char b[260]; struct query_info qinfo; struct iter_hints_stub* stub; regional_free_all(region); qinfo.qname = nm; qinfo.qname_len = nmlen; qinfo.qtype = LDNS_RR_TYPE_A; qinfo.qclass = LDNS_RR_CLASS_IN; qinfo.local_alias = NULL; dname_str(nm, b); if(!ssl_printf(ssl, "The following name servers are used for lookup " "of %s\n", b)) return 0; dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass); if(dp) { if(!ssl_printf(ssl, "forwarding request:\n")) return 0; print_dp_main(ssl, dp, NULL); print_dp_details(ssl, worker, dp); return 1; } while(1) { dp = dns_cache_find_delegation(&worker->env, nm, nmlen, qinfo.qtype, qinfo.qclass, region, &msg, *worker->env.now); if(!dp) { return ssl_printf(ssl, "no delegation from " "cache; goes to configured roots\n"); } /* go up? */ if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) { print_dp_main(ssl, dp, msg); print_dp_details(ssl, worker, dp); if(!ssl_printf(ssl, "cache delegation was " "useless (no IP addresses)\n")) return 0; if(dname_is_root(nm)) { /* goes to root config */ return ssl_printf(ssl, "no delegation from " "cache; goes to configured roots\n"); } else { /* useless, goes up */ nm = dp->name; nmlen = dp->namelen; dname_remove_label(&nm, &nmlen); dname_str(nm, b); if(!ssl_printf(ssl, "going up, lookup %s\n", b)) return 0; continue; } } stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass, dp); if(stub) { if(stub->noprime) { if(!ssl_printf(ssl, "The noprime stub servers " "are used:\n")) return 0; } else { if(!ssl_printf(ssl, "The stub is primed " "with servers:\n")) return 0; } print_dp_main(ssl, stub->dp, NULL); print_dp_details(ssl, worker, stub->dp); } else { print_dp_main(ssl, dp, msg); print_dp_details(ssl, worker, dp); } break; } return 1; }
struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, comm_point_callback_t* callback, void* callback_arg, sldns_buffer* ATTR_UNUSED(buff)) { struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; struct fake_pending* pend = (struct fake_pending*)calloc(1, sizeof(struct fake_pending)); char z[256]; log_assert(pend); log_nametypeclass(VERB_OPS, "pending serviced query", qname, qtype, qclass); dname_str(zone, z); verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s", z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"", (flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":""); /* create packet with EDNS */ pend->buffer = sldns_buffer_new(512); log_assert(pend->buffer); sldns_buffer_write_u16(pend->buffer, 0); /* id */ sldns_buffer_write_u16(pend->buffer, flags); sldns_buffer_write_u16(pend->buffer, 1); /* qdcount */ sldns_buffer_write_u16(pend->buffer, 0); /* ancount */ sldns_buffer_write_u16(pend->buffer, 0); /* nscount */ sldns_buffer_write_u16(pend->buffer, 0); /* arcount */ sldns_buffer_write(pend->buffer, qname, qnamelen); sldns_buffer_write_u16(pend->buffer, qtype); sldns_buffer_write_u16(pend->buffer, qclass); sldns_buffer_flip(pend->buffer); if(1) { /* add edns */ struct edns_data edns; edns.edns_present = 1; edns.ext_rcode = 0; edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits = 0; if(dnssec) edns.bits = EDNS_DO; attach_edns_record(pend->buffer, &edns); } memcpy(&pend->addr, addr, addrlen); pend->addrlen = addrlen; pend->zone = memdup(zone, zonelen); pend->zonelen = zonelen; pend->qtype = (int)qtype; log_assert(pend->zone); pend->callback = callback; pend->cb_arg = callback_arg; pend->timeout = UDP_AUTH_QUERY_TIMEOUT; pend->transport = transport_udp; /* pretend UDP */ pend->pkt = NULL; pend->runtime = runtime; pend->serviced = 1; pend->pkt_len = sldns_buffer_limit(pend->buffer); pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len); if(!pend->pkt) fatal_exit("out of memory"); /*log_pkt("pending serviced query: ", pend->pkt, pend->pkt_len);*/ /* see if it matches the current moment */ if(runtime->now && runtime->now->evt_type == repevt_back_query && (runtime->now->addrlen == 0 || sockaddr_cmp( &runtime->now->addr, runtime->now->addrlen, &pend->addr, pend->addrlen) == 0) && find_match(runtime->now->match, pend->pkt, pend->pkt_len, pend->transport)) { log_info("testbound: matched pending to event. " "advance time between events."); log_info("testbound: do STEP %d %s", runtime->now->time_step, repevt_string(runtime->now->evt_type)); advance_moment(runtime); /* still create the pending, because we need it to callback */ } log_info("testbound: created fake pending"); /* add to list */ pend->next = runtime->pending_list; runtime->pending_list = pend; return (struct serviced_query*)pend; }