/*% * Convert an RR to presentation format. * * return: *\li Number of characters written to buf, or -1 (check errno). */ int ns_sprintrr(const ns_msg* handle, const ns_rr* rr, const char* name_ctx, const char* origin, char* buf, size_t buflen) { int n; n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), name_ctx, origin, buf, buflen); return (n); }
char* getMailserver(const char* domain) { int len; char answer[NS_PACKETSZ]; char *mailserver = malloc(NS_PACKETSZ); ns_msg msg; ns_rr rr; if(res_init() == -1) { return NULL; } len = res_query(domain,C_ANY,T_MX,answer,NS_PACKETSZ); if(len == -1) { return NULL; } /* return first MX record */ ns_initparse(answer,len,&msg); ns_parserr(&msg,ns_s_an,0,&rr); dn_expand(ns_msg_base(msg),ns_msg_base(msg)+ns_msg_size(msg),ns_rr_rdata(rr)+NS_INT16SZ,mailserver,NS_PACKETSZ); return mailserver; }
static int app_parse_srv(radiodns_app_t *app, ns_msg handle, ns_rr rr, char *dnbuf, radiodns_srv_t *srv) { const unsigned char *rdata; (void) app; rdata = ns_rr_rdata(rr); srv->priority = ns_get16(rdata); rdata += NS_INT16SZ; srv->weight = ns_get16(rdata); rdata += NS_INT16SZ; srv->port = ns_get16(rdata); rdata += NS_INT16SZ; dn_expand(ns_msg_base(handle), ns_msg_base(handle) + ns_msg_size(handle), rdata, dnbuf, MAXDNAME); if(!(srv->target = strdup(dnbuf))) { return -2; } return 0; }
void royparse_output(const char* descr, iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char* pkt_copy, unsigned olen, const u_char* payload, unsigned payloadlen) { if (flags & DNSCAP_OUTPUT_ISDNS) { int rrmax; ns_msg msg; ns_rr rr; if (ns_initparse(payload, payloadlen, &msg) < 0) { fprintf(r_out, "ERR\n"); return; } if (ns_msg_getflag(msg, ns_f_qr) != 0 && sport == 53) { fprintf(r_out, "%cD_", ns_msg_getflag(msg, ns_f_rd) ? 'R' : 'N'); switch (ns_msg_getflag(msg, ns_f_opcode)) { case ns_o_query: fprintf(r_out, "QUERY"); break; case ns_o_notify: fprintf(r_out, "NOTIFY"); break; case ns_o_update: fprintf(r_out, "UPDATE"); break; default: fprintf(r_out, "ELSE"); } fprintf(r_out, "_%u_%cA_", ns_msg_count(msg, ns_s_an) ? 1 : 0, ns_msg_getflag(msg, ns_f_aa) ? 'A' : 'N'); switch (ns_msg_getflag(msg, ns_f_rcode)) { case ns_r_noerror: fprintf(r_out, "NOERROR"); break; case ns_r_formerr: fprintf(r_out, "FORMERR"); break; case ns_r_nxdomain: fprintf(r_out, "NXDOMAIN"); break; case ns_r_notimpl: fprintf(r_out, "NOTIMP"); break; case ns_r_refused: fprintf(r_out, "REFUSED"); break; case ns_r_notauth: fprintf(r_out, "NOTAUTH"); break; default: fprintf(r_out, "ELSE"); } fprintf(r_out, " %s,", royparse_ia_str(to)); if (ns_msg_count(msg, ns_s_qd) > 0) { if (ns_parserr(&msg, ns_s_qd, 0, &rr) == 0) { royparse_normalize(ns_rr_name(rr)); fprintf(r_out, "%s%s,%u", ns_rr_name(rr), (ns_rr_name(rr)[0] == '.') ? "" : ".", ns_rr_type(rr)); } else fprintf(r_out, "ERR,ERR"); } else fprintf(r_out, ","); fprintf(r_out, ",%ld,%s%s%s%s", ns_msg_size(msg), ns_msg_id(msg) < 256 ? "-L" : "", ns_msg_getflag(msg, ns_f_tc) ? "-TC" : "", ns_msg_getflag(msg, ns_f_ad) ? "-AD" : "", ns_msg_getflag(msg, ns_f_cd) ? "-CD" : ""); rrmax = ns_msg_count(msg, ns_s_ar); while (rrmax > 0) { rrmax--; if (ns_parserr(&msg, ns_s_ar, rrmax, &rr) == 0) { if (ns_rr_type(rr) == ns_t_opt) { fprintf(r_out, "-%c", (u_long)ns_rr_ttl(rr) & NS_OPT_DNSSEC_OK ? 'D' : 'E'); break; } } } fprintf(r_out, "\n"); } else if (opt_q != 0 && ns_msg_getflag(msg, ns_f_qr) == 0 && dport == 53) { struct pcap_pkthdr h; if (flags & DNSCAP_OUTPUT_ISLAYER) return; memset(&h, 0, sizeof h); h.ts = ts; h.len = h.caplen = olen; pcap_dump((u_char*)q_out, &h, pkt_copy); } } }
/** * create_naptr_record() */ static NAPTR_record *create_naptr_record(const ns_msg *handle, const ns_rr *rr) { size_t rdchars; const u_char *rdata, *edata; const u_char *message = ns_msg_base(*handle); size_t message_len = ns_msg_size(*handle); char buf[NS_MAXDNAME]; /* defined in nameser.h */ NAPTR_record *naptr_record = malloc(sizeof(NAPTR_record)); memset(naptr_record,0,sizeof(NAPTR_record)); /* ** Domain field */ naptr_record->domain = strdup(ns_rr_name(*rr)); /* ** TTL field */ naptr_record->ttl = ns_rr_ttl(*rr); /* ** Copy from rdata ** (borrowed from BIND-8.2.2 ns_print.c) */ rdata = ns_rr_rdata(*rr); edata = rdata+ns_rr_rdlen(*rr); /* ** Order & preference field */ naptr_record->order = ns_get16(rdata); rdata += NS_INT16SZ; naptr_record->preference = ns_get16(rdata); rdata += NS_INT16SZ; /* ** Flags field */ if((naptr_record->flags = get_rdata_str(rdata,edata,&rdchars))==NULL) { free_naptr_record(naptr_record); return NULL; } rdata += rdchars; /* ** Service field */ if((naptr_record->service = get_rdata_str(rdata,edata,&rdchars))==NULL) { free_naptr_record(naptr_record); return NULL; } rdata += rdchars; /* ** RegExp field */ if((naptr_record->regexp = get_rdata_str(rdata,edata,&rdchars))==NULL) { free_naptr_record(naptr_record); return NULL; } rdata += rdchars; /* ** Replacement field ** Note: dn_expand() sets the first character to '\0' for the root, ** we are going to set it back to '.' */ if(dn_expand(message,message+message_len,rdata,buf,NS_MAXDNAME)==-1) { free_naptr_record(naptr_record); return NULL; } if(buf[0]=='\0') { buf[0]='.'; buf[1]='\0'; } naptr_record->replacement = strdup(buf); return naptr_record; }
static int app_follow_ptr(radiodns_app_t *app, unsigned char *abuf, ns_msg phandle, ns_rr prr) { char dnbuf[MAXDNAME + 1], dbuf[4]; char *d, *p, *endp; ns_msg handle; ns_rr rr; int c, len, r; dn_expand(ns_msg_base(phandle), ns_msg_base(phandle) + ns_msg_size(phandle), ns_rr_rdata(prr), dnbuf, sizeof(dnbuf)); if(!(app->name = (char *) calloc(1, strlen(dnbuf)))) { return -2; } d = app->name; p = dnbuf; while(*p && *p != '.') { if(*p == '\\' && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3])) { dbuf[0] = p[1]; dbuf[1] = p[2]; dbuf[2] = p[3]; dbuf[3] = 0; c = strtol(dbuf, NULL, 10); *d = c; d++; p += 4; continue; } else if(*p == '\\' && p[1]) { /* Skip the backslash, allowing it to escape the '.' */ p++; } *d = *p; d++; p++; } *d = 0; if(0 >= (len = res_query(dnbuf, ns_c_in, ns_t_any, abuf, RDNS_ANSWERBUFLEN))) { return -1; } if(0 > ns_initparse(abuf, len, &handle)) { return -1; } if(0 > (len = ns_msg_count(handle, ns_s_an))) { return -1; } if(!(app->srv = (radiodns_srv_t *) calloc(len, sizeof(radiodns_srv_t)))) { return -2; } for(c = 0; c < len; c++) { if(ns_parserr(&handle, ns_s_an, c, &rr)) { continue; } if(ns_rr_class(rr) != ns_c_in) { continue; } if(ns_rr_type(rr) == ns_t_txt) { app_parse_txt(app, handle, rr, dnbuf); } if(ns_rr_type(rr) == ns_t_srv) { r = app_parse_srv(app, handle, rr, dnbuf, &(app->srv[app->nsrv])); if(r == 0) { app->nsrv++; } else { return r; } } } if(app->nsrv) { return 0; } return -1; }
/* Attempt to resolve the target FQDN for a context */ const char * radiodns_resolve_target(radiodns_t *context) { int len, c; ns_msg handle; ns_rr rr; char domain[MAXDNAME + 1], dnbuf[MAXDNAME + 1]; /* reset these to help with error handling in callers */ h_errno = NETDB_INTERNAL; errno = 0; if(!context->answer) { if(NULL == (context->answer = (unsigned char *) malloc(RDNS_ANSWERBUFLEN))) { return NULL; } } free(context->target); context->target = NULL; strcpy(domain, context->domain); for(;;) { h_errno = 0; if(0 >= (len = res_query(domain, ns_c_in, ns_t_any, context->answer, RDNS_ANSWERBUFLEN))) { if(NETDB_INTERNAL == h_errno) { return NULL; } break; } if(0 > ns_initparse(context->answer, len, &handle)) { break; } if(0 > (len = ns_msg_count(handle, ns_s_an))) { break; } /* Resolvers tend towards the sane: the last result in a set of * DNAME and CNAME replies will be the one we care about. If * you're building against a resolver which for some reason * behaves differently, you'll need a workaround here. */ dnbuf[0] = 0; for(c = 0; c < len; c++) { if(ns_parserr(&handle, ns_s_an, c, &rr)) { /* Parse failed? Hmm. */ continue; } if(ns_rr_class(rr) != ns_c_in) { continue; } if(ns_rr_type(rr) == ns_t_dname || ns_rr_type(rr) == ns_t_cname) { dn_expand(ns_msg_base(handle), ns_msg_base(handle) + ns_msg_size(handle), ns_rr_rdata(rr), dnbuf, sizeof(dnbuf)); } } if(dnbuf[0]) { if(0 == strcmp(domain, dnbuf)) { break; } strcpy(domain, dnbuf); continue; } break; } /* Whatever we found last is the target, unless we found nothing at all, * in which case the target is the same as the original domain. */ if(NULL == (context->target = strdup(domain))) { return NULL; } return context->target; }