static const char * print_query(const struct query *q, char *buf, size_t max) { char b[256]; snprintf(buf, max, "%s %s %s", print_dname(q->q_dname, b, sizeof b), __p_class(q->q_class), __p_type(q->q_type)); return (buf); }
static void dns_dispatch_mx_preference(struct asr_result *ar, void *arg) { struct dns_session *s = arg; struct unpack pack; struct dns_header h; struct dns_query q; struct dns_rr rr; char buf[512]; int error; if (ar->ar_h_errno) { if (ar->ar_rcode == NXDOMAIN) error = DNS_ENONAME; else if (ar->ar_h_errno == NO_RECOVERY || ar->ar_h_errno == NO_DATA) error = DNS_EINVAL; else error = DNS_RETRY; } else { error = DNS_ENOTFOUND; unpack_init(&pack, ar->ar_data, ar->ar_datalen); if (unpack_header(&pack, &h) != -1 && unpack_query(&pack, &q) != -1) { for (; h.ancount; h.ancount--) { if (unpack_rr(&pack, &rr) == -1) break; if (rr.rr_type != T_MX) continue; print_dname(rr.rr.mx.exchange, buf, sizeof(buf)); buf[strlen(buf) - 1] = '\0'; if (!strcasecmp(s->name, buf)) { error = DNS_OK; break; } } } } free(ar->ar_data); m_create(s->p, IMSG_MTA_DNS_MX_PREFERENCE, 0, 0, -1); m_add_id(s->p, s->reqid); m_add_int(s->p, error); if (error == DNS_OK) m_add_int(s->p, rr.rr.mx.preference); m_close(s->p); free(s); }
static void dns_dispatch_mx(struct asr_result *ar, void *arg) { struct dns_session *s = arg; struct unpack pack; struct dns_header h; struct dns_query q; struct dns_rr rr; char buf[512]; size_t found; if (ar->ar_h_errno && ar->ar_h_errno != NO_DATA) { m_create(s->p, IMSG_MTA_DNS_HOST_END, 0, 0, -1); m_add_id(s->p, s->reqid); if (ar->ar_rcode == NXDOMAIN) m_add_int(s->p, DNS_ENONAME); else if (ar->ar_h_errno == NO_RECOVERY) m_add_int(s->p, DNS_EINVAL); else m_add_int(s->p, DNS_RETRY); m_close(s->p); free(s); free(ar->ar_data); return; } found = 0; unpack_init(&pack, ar->ar_data, ar->ar_datalen); if (unpack_header(&pack, &h) == -1 || unpack_query(&pack, &q) == -1) return; for (; h.ancount; h.ancount--) { if (unpack_rr(&pack, &rr) == -1) break; if (rr.rr_type != T_MX) continue; print_dname(rr.rr.mx.exchange, buf, sizeof(buf)); buf[strlen(buf) - 1] = '\0'; dns_lookup_host(s, buf, rr.rr.mx.preference); found++; } free(ar->ar_data); /* fallback to host if no MX is found. */ if (found == 0) dns_lookup_host(s, s->name, 0); }
/** list zones in zone tree */ static void list_zones(udb_base* udb, udb_ptr* ztree) { udb_ptr z; for(udb_radix_first(udb,ztree,&z); z.data; udb_radix_next(udb,&z)) { udb_ptr zone; udb_ptr_new(&zone, udb, &RADNODE(&z)->elem); printf("zone: name: \""); print_dname(ZONE(&zone)->name, ZONE(&zone)->namelen); printf("\"\n"); if(v) list_zone_contents(udb, &zone); udb_ptr_unlink(&zone, udb); } udb_ptr_unlink(&z, udb); }
static const char * print_rr(const struct rr *rr, char *buf, size_t max) { char *res; char tmp[256]; char tmp2[256]; int r; res = buf; r = snprintf(buf, max, "%s %u %s %s ", print_dname(rr->rr_dname, tmp, sizeof tmp), rr->rr_ttl, __p_class(rr->rr_class), __p_type(rr->rr_type)); if (r == -1) { buf[0] = '\0'; return (buf); } if ((size_t)r >= max) return (buf); max -= r; buf += r; switch (rr->rr_type) { case T_CNAME: print_dname(rr->rr.cname.cname, buf, max); break; case T_MX: snprintf(buf, max, "%lu %s", (unsigned long)rr->rr.mx.preference, print_dname(rr->rr.mx.exchange, tmp, sizeof tmp)); break; case T_NS: print_dname(rr->rr.ns.nsname, buf, max); break; case T_PTR: print_dname(rr->rr.ptr.ptrname, buf, max); break; case T_SOA: snprintf(buf, max, "%s %s %lu %lu %lu %lu %lu", print_dname(rr->rr.soa.rname, tmp, sizeof tmp), print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2), (unsigned long)rr->rr.soa.serial, (unsigned long)rr->rr.soa.refresh, (unsigned long)rr->rr.soa.retry, (unsigned long)rr->rr.soa.expire, (unsigned long)rr->rr.soa.minimum); break; case T_A: if (rr->rr_class != C_IN) goto other; snprintf(buf, max, "%s", inet_ntop(AF_INET, &rr->rr.in_a.addr, tmp, sizeof tmp)); break; case T_AAAA: if (rr->rr_class != C_IN) goto other; snprintf(buf, max, "%s", inet_ntop(AF_INET6, &rr->rr.in_aaaa.addr6, tmp, sizeof tmp)); break; default: other: snprintf(buf, max, "(rdlen=%i)", (int)rr->rr.other.rdlen); break; } return (res); }
/** inspect a chunk in the file */ static void* inspect_chunk(void* base, void* cv, struct inspect_totals* t) { udb_chunk_d* cp = (udb_chunk_d*)cv; udb_void c = (udb_void)(cv - base); udb_void data; uint8_t exp = cp->exp; uint8_t tp = cp->type; uint8_t flags = cp->flags; uint64_t sz = 0; if(exp == UDB_EXP_XL) { sz = ((udb_xl_chunk_d*)cp)->size; data = c + sizeof(udb_xl_chunk_d); } else { sz = (uint64_t)1<<exp; data = c + sizeof(udb_chunk_d); } if(v) { /* print chunk details */ printf("chunk at %llu exp=%d type=%d (%s) flags=0x%x " "size=%llu\n", ULL c, exp, tp, chunk_type2str(tp), flags, ULL sz); if(tp == udb_chunk_type_free) { udb_free_chunk_d* fp = (udb_free_chunk_d*)cp; printf("prev: %llu\n", ULL fp->prev); printf("next: %llu\n", ULL fp->next); } else { printf("ptrlist: %llu\n", ULL cp->ptrlist); } } if(v>=2 && tp != udb_chunk_type_free && cp->ptrlist) { /* follow the pointer list */ udb_rel_ptr* pl = UDB_REL_PTR(cp->ptrlist); while(pl->next) { printf("relptr %llu\n", ULL UDB_SYSTOREL(base, pl)); printf(" prev-ptrlist: %llu\n", ULL pl->prev); printf(" data: %llu\n", ULL pl->data); printf(" next-ptrlist: %llu\n", ULL pl->next); pl = UDB_REL_PTR(pl->next); } } /* print data details */ if(v>=2) { if(cp->type == udb_chunk_type_radtree) { struct udb_radtree_d* d = (struct udb_radtree_d*)UDB_REL(base, data); printf(" radtree count=%llu root=%llu\n", ULL d->count, ULL d->root.data); } else if(cp->type == udb_chunk_type_radnode) { struct udb_radnode_d* d = (struct udb_radnode_d*)UDB_REL(base, data); printf(" radnode pidx=%d offset=%d elem=%llu " "parent=%llu lookup=%llu\n", (int)d->pidx, (int)d->offset, ULL d->elem.data, ULL d->parent.data, ULL d->lookup.data); } else if(cp->type == udb_chunk_type_radarray) { struct udb_radarray_d* d = (struct udb_radarray_d*)UDB_REL( base, data); unsigned i; printf(" radarray len=%d capacity=%d str_cap=%d\n", (int)d->len, (int)d->capacity, (int)d->str_cap); for(i=0; i<d->len; i++) if(d->array[i].node.data) { printf(" [%u] node=%llu len=%d ", i, ULL d->array[i].node.data, (int)d->array[i].len); print_escaped( ((uint8_t*)&d->array[d->capacity])+ i*d->str_cap, (size_t)d->array[i].len); printf("\n"); } } else if(cp->type == udb_chunk_type_zone) { struct zone_d* d = (struct zone_d*)UDB_REL(base, data); printf(" zone "); print_dname(d->name, d->namelen); printf(" rr_count=%llu rrset_count=%llu expired=%d " "node=%llu domains=%llu\n", ULL d->rr_count, ULL d->rrset_count, (int)d->expired, ULL d->node.data, ULL d->domains.data); } else if(cp->type == udb_chunk_type_domain) { struct domain_d* d = (struct domain_d*)UDB_REL(base, data); printf(" domain "); print_dname(d->name, d->namelen); printf(" node=%llu rrsets=%llu\n", ULL d->node.data, ULL d->rrsets.data); } else if(cp->type == udb_chunk_type_rrset) { struct rrset_d* d = (struct rrset_d*)UDB_REL(base, data); printf(" rrset type=%d next=%llu rrs=%llu\n", (int)d->type, ULL d->next.data, ULL d->rrs.data); } else if(cp->type == udb_chunk_type_rr) { struct rr_d* d = (struct rr_d*)UDB_REL(base, data); printf(" rr type=%d class=%d ttl=%u next=%llu len=%d ", (int)d->type, (int)d->klass, (unsigned)d->ttl, ULL d->next.data, (int)d->len); print_hex(d->wire, d->len); printf("\n"); } else if(cp->type == udb_chunk_type_task) { struct task_list_d* d = (struct task_list_d*)UDB_REL(base, data); printf(" task type=%d next=%llu yesno=%d oldserial=%u newserial=%u zone=%s\n", (int)d->task_type, ULL d->next.data, (int)d->yesno, (unsigned)d->oldserial, (unsigned)d->newserial, d->size > sizeof(*d)? dname_to_string(d->zname, NULL):"\"\""); } } /* end verbosity 2 */ /* update stats */ t->exp_num[exp]++; if(tp == udb_chunk_type_free) { t->exp_free[exp]++; } else { t->type_num[tp]++; t->type_exp_num[tp][exp]++; } /* check end marker */ if(exp == UDB_EXP_XL) { if(sz != *(uint64_t*)(cv+sz-2*sizeof(uint64_t))) { printf(" end xl size is wrong: %llu\n", ULL *(uint64_t*)(cv+sz-2*sizeof(uint64_t))); } } if(exp != *(uint8_t*)(cv+sz-1)) { printf(" end exp is wrong: %d\n", *(uint8_t*)(cv+sz-1)); } return cv+sz; }