static int print_axfr(FILE *file, const u_char *msg, size_t msglen) { ns_msg handle; if (ns_initparse(msg, msglen, &handle) < 0) { fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); return (ns_r_formerr); } if (ns_msg_getflag(handle, ns_f_rcode) != ns_r_noerror) return (ns_msg_getflag(handle, ns_f_rcode)); /* * We are looking for info from answer resource records. * If there aren't any, return with an error. We assume * there aren't any question records. */ if (ns_msg_count(handle, ns_s_an) == 0) return (NO_INFO); #ifdef PROTOCOLDEBUG printf(";;; (message of %d octets has %d answers)\n", msglen, ns_msg_count(handle, ns_s_an)); #endif for (;;) { static char origin[NS_MAXDNAME], name_ctx[NS_MAXDNAME]; const char *name; char buf[2048]; /* XXX need to malloc/realloc. */ ns_rr rr; if (ns_parserr(&handle, ns_s_an, -1, &rr)) { if (errno != ENODEV) { fprintf(file, ";; ns_parserr: %s\n", strerror(errno)); return (FORMERR); } break; } name = ns_rr_name(rr); if (origin[0] == '\0' && name[0] != '\0') { if (strcmp(name, ".") != 0) strcpy(origin, name); fprintf(file, "$ORIGIN %s.\n", origin); if (strcmp(name, ".") == 0) strcpy(origin, name); if (res.pfcode & RES_PRF_TRUNC) strcpy(name_ctx, "@"); } if (ns_sprintrr(&handle, &rr, (res.pfcode & RES_PRF_TRUNC) ? name_ctx : NULL, (res.pfcode & RES_PRF_TRUNC) ? origin : NULL, buf, sizeof buf) < 0) { fprintf(file, ";; ns_sprintrr: %s\n", strerror(errno)); return (FORMERR); } strcpy(name_ctx, name); fputs(buf, file); fputc('\n', file); } return (SUCCESS); }
static void parse_answer_section(ns_msg *msg) { int rrnum, rrmax; ns_rr rr; uint16_t prio, weight, port, len; const unsigned char *rdata; char *tname; rrmax = ns_msg_count(*msg, ns_s_an); for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(msg, ns_s_an, rrnum, &rr)) { perror("ns_parserr"); exit(EXIT_FAILURE); } if (ns_rr_type(rr) == ns_t_srv) { len = ns_rr_rdlen(rr); rdata = ns_rr_rdata(rr); if (len > 3U * NS_INT16SZ) { NS_GET16(prio, rdata); NS_GET16(weight, rdata); NS_GET16(port, rdata); len -= 3U * NS_INT16SZ; tname = target_name(rdata); insert_tuple(tname, prio, weight, port); } } } }
const char * hostname_from_question(ns_msg msg) { static char hostname[256] = {0}; ns_rr rr; int rrnum, rrmax; const char *result; int result_len; rrmax = ns_msg_count(msg, ns_s_qd); if (rrmax == 0) return NULL; for (rrnum = 0; rrnum < rrmax; rrnum++) { if (local_ns_parserr(&msg, ns_s_qd, rrnum, &rr)) { logger_log(LOG_ERR, "local_ns_parserr"); return NULL; } result = ns_rr_name(rr); result_len = strlen(result) + 1; if (result_len > sizeof(hostname)) { logger_log(LOG_ERR, "hostname too long: %s", result); } memset(hostname, 0, sizeof(hostname)); memcpy(hostname, result, result_len); return hostname; } return NULL; }
static void test_res_fake_a_query_case_insensitive(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; char addr[INET_ADDRSTRLEN]; ns_msg handle; ns_rr rr; /* expanded resource record */ (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "CWRAP.ORG", ns_c_in, ns_t_a, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type A and have the address that our * fake hosts file contains. Case does not matter. */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.21"); res_nclose(&dnsstate); }
KDCENTRY* krb_locate_kdc(rdpSettings* settings) { #ifdef WITH_RESOLV char *qname; int reslen, i; unsigned char response[4096]; char kdc_host[4096]; unsigned char* temp; KDCENTRY* head; KDCENTRY* kdcentry; KDCENTRY* srvans; ns_msg handle; ns_rr rr; head = kdcentry = NULL; if (get_krb_realm(settings)) return NULL; if (settings->kerberos_kdc) { srvans = xnew(KDCENTRY); srvans->kdchost = xstrdup(settings->kerberos_kdc); srvans->port = 88; return srvans; } qname = get_dns_queryname(settings->kerberos_realm, "_tcp."); if ((reslen = res_query(qname, ns_c_in, ns_t_srv, response, sizeof(response))) < 0) return NULL; ns_initparse(response, reslen, &handle); for (i = 0;i < ns_msg_count(handle, ns_s_an);i++) { ns_parserr(&handle, ns_s_an, i, &rr); srvans = xnew(KDCENTRY); temp = (unsigned char*)ns_rr_rdata(rr); GETUINT16(temp, &(srvans->priority)); GETUINT16(temp, &(srvans->weight)); GETUINT16(temp, &(srvans->port)); if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), temp, (char*)kdc_host, sizeof(kdc_host)) < 0) srvans->kdchost = xstrdup((const char*)temp); else srvans->kdchost = xstrdup(kdc_host); if (head == NULL || head->priority > srvans->priority) { srvans->next = head; head = srvans; } else { for (kdcentry = head;kdcentry->next != NULL && kdcentry->next->priority < srvans->priority;kdcentry = kdcentry->next); srvans->next = kdcentry->next; kdcentry->next = srvans; } } return head; #else return NULL; #endif }
static int should_filter_query(ns_msg msg, struct in_addr dns_addr) { ns_rr rr; int rrnum, rrmax; void *r; // TODO cache result for each dns server int dns_is_chn = chnroute_file && (dns_servers_len > 1) && test_ip_in_list(dns_addr, &chnroute_list); rrmax = ns_msg_count(msg, ns_s_an); if (rrmax == 0) return -1; for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(&msg, ns_s_an, rrnum, &rr)) { ERR("ns_parserr"); return 0; } u_int type; const u_char *rd; type = ns_rr_type(rr); rd = ns_rr_rdata(rr); if (type == ns_t_a) { if (verbose) printf("%s, ", inet_ntoa(*(struct in_addr *)rd)); r = bsearch(rd, ip_list.ips, ip_list.entries, sizeof(struct in_addr), cmp_in_addr); if (r) return 1; if (chnroute_file && dns_is_chn) { // filter DNS result from chn dns if result is outside chn if (!test_ip_in_list(*(struct in_addr *)rd, &chnroute_list)) return 1; } } } return 0; }
static void test_res_fake_aaaa_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; char addr[INET6_ADDRSTRLEN]; ns_msg handle; ns_rr rr; /* expanded resource record */ (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "cwrap6.org", ns_c_in, ns_t_aaaa, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type AAAA and have the address that our * fake hosts file contains */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_aaaa); assert_non_null(inet_ntop(AF_INET6, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "2a00:1450:4013:c01::63"); }
/** * @return 成功した場合は NETDB_SUCCESS. */ static int DnsResolver_lookupTxtData(DnsResolver *self, int rrtype, const char *domain, DnsTxtResponse **resp) { int query_stat = DnsResolver_query(self, domain, rrtype); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsTxtResponse *respobj = (DnsTxtResponse *) malloc(sizeof(DnsTxtResponse) + msg_count * sizeof(char *)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsTxtResponse) + msg_count * sizeof(char *)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_txt != ns_rr_type(rr)) { continue; } // end if respobj->data[respobj->num] = (char *) malloc(ns_rr_rdlen(rr)); // RDLEN を越えることはない. if (NULL == respobj->data[respobj->num]) { goto noresource; } // end if const unsigned char *rdata = ns_rr_rdata(rr); const unsigned char *rdata_tail = ns_rr_rdata(rr) + ns_rr_rdlen(rr); char *bufp = respobj->data[respobj->num]; while (rdata < rdata_tail) { // 長さフィールドが RDLEN の中に収まっているか確認する if (rdata_tail < rdata + (*rdata) + 1) { free(respobj->data[respobj->num]); goto formerr; } // end if memcpy(bufp, rdata + 1, *rdata); bufp += (size_t) *rdata; rdata += (size_t) *rdata + 1; } // end while *bufp = '\0'; // 扱いやすいように NULL 終端させる ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsTxtResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); noresource: DnsTxtResponse_free(respobj); return DnsResolver_setError(self, NETDB_INTERNAL); } // end function : DnsResolver_lookupTxtData
static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options, PDNS_RECORDA *result ) { DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED; unsigned int i, num; unsigned char answer[NS_PACKETSZ]; ns_sect sections[] = { ns_s_an, ns_s_ar }; ns_msg msg; DNS_RECORDA *record = NULL; DNS_RRSET rrset; int len; DNS_RRSET_INIT( rrset ); len = res_query( name, ns_c_in, type, answer, sizeof(answer) ); if (len < 0) { ret = dns_map_h_errno( h_errno ); goto exit; } if (dns_ns_initparse( answer, len, &msg ) < 0) { ret = DNS_ERROR_BAD_PACKET; goto exit; } #define RCODE_MASK 0x0f if ((msg._flags & RCODE_MASK) != ns_r_noerror) { ret = dns_map_error( msg._flags & RCODE_MASK ); goto exit; } for (i = 0; i < sizeof(sections)/sizeof(sections[0]); i++) { for (num = 0; num < ns_msg_count( msg, sections[i] ); num++) { ret = dns_copy_record( msg, sections[i], num, &record ); if (ret != ERROR_SUCCESS) goto exit; DNS_RRSET_ADD( rrset, (DNS_RECORD *)record ); } } exit: DNS_RRSET_TERMINATE( rrset ); if (ret != ERROR_SUCCESS) DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList ); else *result = (DNS_RECORDA *)rrset.pFirstRR; return ret; }
static void test_res_fake_srv_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; int prio; int weight; int port; char hostname[MAXDNAME]; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "_ldap._tcp.cwrap.org", ns_c_in, ns_t_srv, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type SRV and have the priority, weight, * port and hostname as in the fake hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_srv); rrdata = ns_rr_rdata(rr); NS_GET16(prio, rrdata); NS_GET16(weight, rrdata); NS_GET16(port, rrdata); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, hostname, MAXDNAME); assert_int_not_equal(rv, -1); assert_int_equal(prio, 1); assert_int_equal(weight, 5); assert_int_equal(port, 389); assert_string_equal(hostname, "ldap.cwrap.org"); }
int count_mx (const char *host) { u_char nsbuf[4096]; ns_msg amsg; int l; l = res_query (host, ns_c_any, ns_t_mx, nsbuf, sizeof (nsbuf)); if (l < 0) { return 0; } else { ns_initparse (nsbuf, l, &amsg); l = ns_msg_count (amsg, ns_s_an); } return l; }
int DnsResolver_lookupAaaa(DnsResolver *self, const char *domain, DnsAaaaResponse **resp) { int query_stat = DnsResolver_query(self, domain, ns_t_aaaa); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsAaaaResponse *respobj = (DnsAaaaResponse *) malloc(sizeof(DnsAaaaResponse) + msg_count * sizeof(struct in6_addr)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsAaaaResponse) + msg_count * sizeof(struct in6_addr)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_aaaa != ns_rr_type(rr)) { continue; } // end if if (NS_IN6ADDRSZ != ns_rr_rdlen(rr)) { goto formerr; } // end if memcpy(&(respobj->addr[respobj->num]), ns_rr_rdata(rr), NS_IN6ADDRSZ); ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsAaaaResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); } // end function : DnsResolver_lookupAaaa
static void test_res_fake_aaaa_query_notfound(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "nosuchentry.org", ns_c_in, ns_t_aaaa, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* The query must finish w/o an error and have no answer */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 0); }
static void dump_dns_sect(ns_msg *msg, ns_sect sect, FILE *trace, const char *endline) { int rrnum, rrmax; const char *sep; ns_rr rr; rrmax = ns_msg_count(*msg, sect); if (rrmax == 0) { fputs(" 0", trace); return; } fprintf(trace, " %s%d", endline, rrmax); sep = ""; for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(msg, sect, rrnum, &rr)) { fputs(strerror(errno), trace); return; } fprintf(trace, " %s", sep); dump_dns_rr(msg, &rr, sect, trace); sep = endline; } }
/* * krb5int_dns_nextans - get next matching answer record * * Sets pp to NULL if no more records. Returns -1 on error, 0 on * success. */ int krb5int_dns_nextans(struct krb5int_dns_state *ds, const unsigned char **pp, int *lenp) { int len; ns_rr rr; *pp = NULL; *lenp = 0; while (ds->cur_ans < ns_msg_count(ds->msg, ns_s_an)) { len = ns_parserr(&ds->msg, ns_s_an, ds->cur_ans, &rr); if (len < 0) return -1; ds->cur_ans++; if (ds->nclass == (int)ns_rr_class(rr) && ds->ntype == (int)ns_rr_type(rr)) { *pp = ns_rr_rdata(rr); *lenp = ns_rr_rdlen(rr); return 0; } } return 0; }
/* Initialize a "newmsg" object by copying an existing parsed message. */ int ns_newmsg_copy(ns_newmsg *handle, ns_msg *msg) { ns_flag flag; ns_sect sect; ns_newmsg_id(handle, ns_msg_id(*msg)); for (flag = ns_f_qr; flag < ns_f_max; flag++) ns_newmsg_flag(handle, flag, ns_msg_getflag(*msg, flag)); for (sect = ns_s_qd; sect < ns_s_max; sect++) { int i, count; count = ns_msg_count(*msg, sect); for (i = 0; i < count; i++) { ns_rr2 rr; int x; if (ns_parserr2(msg, sect, i, &rr) < 0) return (-1); if (sect == ns_s_qd) x = ns_newmsg_q(handle, ns_rr_nname(rr), ns_rr_type(rr), ns_rr_class(rr)); else x = ns_newmsg_rr(handle, sect, ns_rr_nname(rr), ns_rr_type(rr), ns_rr_class(rr), ns_rr_ttl(rr), ns_rr_rdlen(rr), ns_rr_rdata(rr)); if (x < 0) return (-1); } } return (0); }
static const char *hostname_from_question(ns_msg msg) { ns_rr rr; int rrnum, rrmax; const char *result; int result_len; rrmax = ns_msg_count(msg, ns_s_qd); if (rrmax == 0) return NULL; for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(&msg, ns_s_qd, rrnum, &rr)) { ERR("ns_parserr"); return NULL; } result = ns_rr_name(rr); result_len = strlen(result) + 1; if (result_len > hostname_buflen) { hostname_buflen = result_len << 1; hostname_buf = realloc(hostname_buf, hostname_buflen); } memcpy(hostname_buf, result, result_len); return hostname_buf; } return NULL; }
static JSBool parse_section(JSContext *cx, JSObject *sobj, ns_msg *hdl, ns_sect sect) { int rrnum, i; ns_rr rr; JSObject *robj; JSString *name; for (rrnum = 0; rrnum < ns_msg_count(*hdl, sect); rrnum++) { if (ns_parserr(hdl, sect, rrnum, &rr) < 0) return JS_RetError(cx, "ns_parserr: %s", strerror(errno)); robj = JS_NewObject(cx, NULL, NULL, NULL); if (!robj) return JS_RetErrno(cx, ENOMEM); if (!JS_DefineElement(cx, sobj, rrnum, OBJECT_TO_JSVAL(robj), NULL, NULL, JSPROP_ENUMERATE)) return JS_RetErrno(cx, ENOMEM); name = JS_NewStringCopyZ(cx, ns_rr_name(rr)); if (!name || !JS_DefineProperty(cx, robj, "name", STRING_TO_JSVAL(name), NULL, NULL, JSPROP_ENUMERATE)) return JS_RetErrno(cx, ENOMEM); if (!JS_DefineProperty(cx, robj, "type", INT_TO_JSVAL(ns_rr_type(rr)), NULL, NULL, JSPROP_ENUMERATE)) return JS_RetErrno(cx, ENOMEM); for (i = 0; i < ARRAY_SIZE(pmap); i++) { if (pmap[i].type != ns_rr_type(rr)) continue; if (!pmap[i].func(cx, robj, hdl, &rr)) return JS_FALSE; break; } } return JS_TRUE; }
void dowse_output(const char *descr, iaddr from, iaddr to, uint8_t proto, int isfrag, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char *pkt_copy, unsigned olen, const u_char *dnspkt, unsigned dnslen) { /* dnspkt may be NULL if IP packet does not contain a valid DNS message */ char output[MAX_OUTPUT]; if (dnspkt) { ns_msg msg; int qdcount; ns_rr rr; int *val; char *sval; char *extracted; char *resolved; char *from; int res; char action = 'A'; char from_color[16]; ns_initparse(dnspkt, dnslen, &msg); if (!ns_msg_getflag(msg, ns_f_qr)) return; /* * -- flags -- * 0 1 5 6 7 8 11 15 * +----+----------------+----+----+----+-----------+----------------+ * | QR | Operation Code | AA | TC | RA | Zero | Recode | * +----+----------------+----+----+----+-----------+----------------+ * * Question/Response : ns_f_qr * Operation code : ns_f_opcode * Authoritative Answer : ns_f_aa * Truncation occurred : ns_f_tc * Recursion Desired : ns_f_rd * Recursion Available : ns_f_ra * MBZ : ns_f_z * Authentic Data (DNSSEC) : ns_f_ad * Checking Disabled (DNSSEC) : ns_f_cd * Response code : ns_f_rcode */ // logerr("msg: %p",msg); qdcount = ns_msg_count(msg, ns_s_qd); if (qdcount > 0 && 0 == ns_parserr(&msg, ns_s_qd, 0, &rr)) { // where the query comes from from = ia_resolv(to); // if its from ourselves omit it if(strncmp(from,hostname,MAX_DOMAIN)==0) return; if(own_ipv4) if(strncmp(from,own_ipv4,MAX_DOMAIN)==0) return; // not reverse resolved means not known by Dowse, code RED if(is_ip(from)) strcpy(from_color,"#FF0000"); resolved = ns_rr_name(rr); // what domain is being looked up extracted = extract_domain(resolved); res = hashmap_get(visited, extracted, (void**)(&val)); switch(res) { case MAP_MISSING : // never visited val = malloc(sizeof(int)); *val = 1; // just a placeholder for now res = hashmap_put(visited, strdup(extracted), val); break; case MAP_OK: // already visited action = 'M'; break; // TODO error checks case MAP_FULL: case MAP_OMEM: break; } // compose the path of the detected query // add category if listed if(listpath) { // add known domain list information res = hashmap_get(domainlist, extracted, (void**)(&sval)); switch(res) { case MAP_OK: /* render with the category in front of domain */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s/%s", ts.tv_sec, from, action, tld, sval, extracted); break; default: /* render only the domain in root category */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s", ts.tv_sec, from, action, tld, extracted); break; } } else /* render only the domain in root category */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s", ts.tv_sec, from, action, tld, extracted); /* write to file */ if(fileout) { fputs(output, fileout); fputc('\n',fileout); if(fileout) fflush(fileout); } /* print fast on console for realtime */ if(console) { puts(output); fflush(stdout); } } } }
static void test_res_fake_soa_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; char nameser[MAXDNAME]; char admin[MAXDNAME]; int serial; int refresh; int retry; int expire; int minimum; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "cwrap.org", ns_c_in, ns_t_soa, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type SOA and have the data as in the fake * hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_soa); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, nameser, MAXDNAME); assert_int_not_equal(rv, -1); rrdata += rv; rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, admin, MAXDNAME); assert_int_not_equal(rv, -1); rrdata += rv; NS_GET32(serial, rrdata); NS_GET32(refresh, rrdata); NS_GET32(retry, rrdata); NS_GET32(expire, rrdata); NS_GET32(minimum, rrdata); assert_string_equal(nameser, "ns1.cwrap.org"); assert_string_equal(admin, "admin.cwrap.org"); assert_int_equal(serial, 2014100457); assert_int_equal(refresh, 3600); assert_int_equal(retry, 300); assert_int_equal(expire, 1814400); assert_int_equal(minimum, 600); }
void txtout_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) { /* * Short output, only print QTYPE and QNAME for IN records */ if (opt_s) { if (flags & DNSCAP_OUTPUT_ISDNS) { ns_msg msg; int qdcount, err = 0; ns_rr rr; if (ns_initparse(payload, payloadlen, &msg) < 0) { if (tcpstate_getcurr && tcpstate_reset) tcpstate_reset(tcpstate_getcurr(), ""); return; } qdcount = ns_msg_count(msg, ns_s_qd); if (qdcount > 0 && 0 == (err = ns_parserr(&msg, ns_s_qd, 0, &rr)) && ns_rr_class(rr) == 1) { fprintf(out, "%s %s\n", p_type(ns_rr_type(rr)), ns_rr_name(rr)); } if (err < 0) { if (tcpstate_getcurr && tcpstate_reset) tcpstate_reset(tcpstate_getcurr(), ""); } } return; } /* * IP Stuff */ fprintf(out, "%10ld.%06ld", (long)ts.tv_sec, (long)ts.tv_usec); fprintf(out, " %s %u", ia_str(from), sport); fprintf(out, " %s %u", ia_str(to), dport); fprintf(out, " %hhu", proto); if (flags & DNSCAP_OUTPUT_ISDNS) { ns_msg msg; int qdcount, err = 0; ns_rr rr; if (ns_initparse(payload, payloadlen, &msg) < 0) { if (tcpstate_getcurr && tcpstate_reset) tcpstate_reset(tcpstate_getcurr(), ""); fprintf(out, "\n"); return; } /* * DNS Header */ fprintf(out, " %u", ns_msg_id(msg)); fprintf(out, " %u", ns_msg_getflag(msg, ns_f_opcode)); fprintf(out, " %u", ns_msg_getflag(msg, ns_f_rcode)); fprintf(out, " |"); if (ns_msg_getflag(msg, ns_f_qr)) fprintf(out, "QR|"); if (ns_msg_getflag(msg, ns_f_aa)) fprintf(out, "AA|"); if (ns_msg_getflag(msg, ns_f_tc)) fprintf(out, "TC|"); if (ns_msg_getflag(msg, ns_f_rd)) fprintf(out, "RD|"); if (ns_msg_getflag(msg, ns_f_ra)) fprintf(out, "RA|"); if (ns_msg_getflag(msg, ns_f_ad)) fprintf(out, "AD|"); if (ns_msg_getflag(msg, ns_f_cd)) fprintf(out, "CD|"); qdcount = ns_msg_count(msg, ns_s_qd); if (qdcount > 0 && 0 == (err = ns_parserr(&msg, ns_s_qd, 0, &rr))) { fprintf(out, " %s %s %s", p_class(ns_rr_class(rr)), p_type(ns_rr_type(rr)), ns_rr_name(rr)); } if (err < 0) { if (tcpstate_getcurr && tcpstate_reset) tcpstate_reset(tcpstate_getcurr(), ""); } } /* * Done */ fprintf(out, "\n"); }
static void test_res_fake_cname_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; char cname[MAXDNAME]; char addr[INET_ADDRSTRLEN]; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_cname, answer, sizeof(answer)); assert_in_range(rv, 1, 256); ns_initparse(answer, 256, &handle); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type CNAME and have the cname as in the * fake hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "web.cwrap.org"); /* The CNAME points to an A record that's present in the additional * section */ assert_int_equal(ns_msg_count(handle, ns_s_ar), 2); assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); assert_string_equal(ns_rr_name(rr), "web.cwrap.org"); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "www.cwrap.org"); assert_int_equal(ns_parserr(&handle, ns_s_ar, 1, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_string_equal(ns_rr_name(rr), "www.cwrap.org"); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.22"); }
static void test_res_fake_a_via_cname(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; char cname[MAXDNAME]; char addr[INET_ADDRSTRLEN]; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); /* Query for A record, but the key is a CNAME. The expected result is * that the whole chain of CNAMEs will be included in the answer section * along with the resulting A */ rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_a, answer, sizeof(answer)); assert_in_range(rv, 1, 256); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have three answers and the answers * must be a parseable RR of type CNAME and have the cname as in the * fake hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 3); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "web.cwrap.org"); assert_int_equal(ns_parserr(&handle, ns_s_an, 1, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "www.cwrap.org"); assert_int_equal(ns_parserr(&handle, ns_s_an, 2, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_string_equal(ns_rr_name(rr), "www.cwrap.org"); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.22"); }
static void afsdb_hosts_to_addrs(char *vllist[], int *vlsnum, ns_msg handle, ns_sect section, unsigned mask, unsigned long *_ttl) { int rrnum; ns_rr rr; int subtype, i, ret; unsigned int ttl = UINT_MAX, rr_ttl; debug("AFSDB RR count is %d", ns_msg_count(handle, section)); /* Look at all the resource records in this section. */ for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { /* Expand the resource record number rrnum into rr. */ if (ns_parserr(&handle, section, rrnum, &rr)) { _error("ns_parserr failed : %m"); continue; } /* We're only interested in AFSDB records */ if (ns_rr_type(rr) == ns_t_afsdb) { vllist[*vlsnum] = malloc(MAXDNAME); if (!vllist[*vlsnum]) error("Out of memory"); subtype = ns_get16(ns_rr_rdata(rr)); /* Expand the name server's domain name */ if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr) + 2, vllist[*vlsnum], MAXDNAME) < 0) error("ns_name_uncompress failed"); rr_ttl = ns_rr_ttl(rr); if (ttl > rr_ttl) ttl = rr_ttl; /* Check the domain name we've just unpacked and add it to * the list of VL servers if it is not a duplicate. * If it is a duplicate, just ignore it. */ for (i = 0; i < *vlsnum; i++) if (strcasecmp(vllist[i], vllist[*vlsnum]) == 0) goto next_one; /* Turn the hostname into IP addresses */ ret = dns_resolver(vllist[*vlsnum], mask); if (ret) { debug("AFSDB RR can't resolve." "subtype:%d, server name:%s, netmask:%u", subtype, vllist[*vlsnum], mask); goto next_one; } info("AFSDB RR subtype:%d, server name:%s, ip:%*.*s, ttl:%u", subtype, vllist[*vlsnum], (int)payload[payload_index - 1].iov_len, (int)payload[payload_index - 1].iov_len, (char *)payload[payload_index - 1].iov_base, ttl); /* prepare for the next record */ *vlsnum += 1; continue; next_one: free(vllist[*vlsnum]); } } *_ttl = ttl; info("ttl: %u", ttl); }
int DnsResolver_lookupPtr(DnsResolver *self, int af, const void *addr, DnsPtrResponse **resp) { // IPv6 の逆引きエントリ名生成に十分な長さのバッファを確保する. char domain[DNS_IP6_REVENT_MAXLEN]; switch (af) { case AF_INET: if (!DnsResolver_expandReverseEntry4(addr, domain, sizeof(domain))) { abort(); } // end if break; case AF_INET6: if (!DnsResolver_expandReverseEntry6(addr, domain, sizeof(domain))) { abort(); } // end if break; default: errno = EAFNOSUPPORT; return NETDB_INTERNAL; } // end if int query_stat = DnsResolver_query(self, domain, ns_t_ptr); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsPtrResponse *respobj = (DnsPtrResponse *) malloc(sizeof(DnsPtrResponse) + msg_count * sizeof(char *)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsPtrResponse) + msg_count * sizeof(char *)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_ptr != ns_rr_type(rr)) { continue; } // end if // NOTE: NS_MAXDNAME で十分なのかイマイチ確証が持てないが, bind8 の dig コマンドの実装でもこの値を使っていたのでいいのではないか. char dnamebuf[NS_MAXDNAME]; int dnamelen = ns_name_uncompress(self->msgbuf, self->msgbuf + self->msglen, ns_rr_rdata(rr), dnamebuf, sizeof(dnamebuf)); if (dnamelen != ns_rr_rdlen(rr)) { goto formerr; } // end if respobj->domain[respobj->num] = strdup(dnamebuf); if (NULL == respobj->domain[respobj->num]) { goto noresource; } // end if ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsPtrResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); noresource: DnsPtrResponse_free(respobj); return DnsResolver_setError(self, NETDB_INTERNAL); } // end function : DnsResolver_lookupPtr
/* * Print the contents of a query. * This is intended to be primarily a debugging routine. */ void fp_nquery (const unsigned char *msg, int len, FILE *file) { ns_msg handle; int qdcount, ancount, nscount, arcount; u_int opcode, rcode, id; /* There is no need to initialize _res: If _res is not yet initialized, _res.pfcode is zero. But initialization will leave it at zero, too. _res.pfcode is an unsigned long, but the code here assumes that the flags fit into an int, so use that. */ int pfcode = _res.pfcode; if (ns_initparse(msg, len, &handle) < 0) { fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); return; } opcode = ns_msg_getflag(handle, ns_f_opcode); rcode = ns_msg_getflag(handle, ns_f_rcode); id = ns_msg_id(handle); qdcount = ns_msg_count(handle, ns_s_qd); ancount = ns_msg_count(handle, ns_s_an); nscount = ns_msg_count(handle, ns_s_ns); arcount = ns_msg_count(handle, ns_s_ar); /* * Print header fields. */ if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode) fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", res_opcodes[opcode], p_rcode(rcode), id); if ((!pfcode) || (pfcode & RES_PRF_HEADX)) putc(';', file); if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) { fprintf(file, "; flags:"); if (ns_msg_getflag(handle, ns_f_qr)) fprintf(file, " qr"); if (ns_msg_getflag(handle, ns_f_aa)) fprintf(file, " aa"); if (ns_msg_getflag(handle, ns_f_tc)) fprintf(file, " tc"); if (ns_msg_getflag(handle, ns_f_rd)) fprintf(file, " rd"); if (ns_msg_getflag(handle, ns_f_ra)) fprintf(file, " ra"); if (ns_msg_getflag(handle, ns_f_z)) fprintf(file, " ??"); if (ns_msg_getflag(handle, ns_f_ad)) fprintf(file, " ad"); if (ns_msg_getflag(handle, ns_f_cd)) fprintf(file, " cd"); } if ((!pfcode) || (pfcode & RES_PRF_HEAD1)) { fprintf(file, "; %s: %d", p_section(ns_s_qd, opcode), qdcount); fprintf(file, ", %s: %d", p_section(ns_s_an, opcode), ancount); fprintf(file, ", %s: %d", p_section(ns_s_ns, opcode), nscount); fprintf(file, ", %s: %d", p_section(ns_s_ar, opcode), arcount); } if ((!pfcode) || (pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { putc('\n',file); } /* * Print the various sections. */ do_section (pfcode, &handle, ns_s_qd, RES_PRF_QUES, file); do_section (pfcode, &handle, ns_s_an, RES_PRF_ANS, file); do_section (pfcode, &handle, ns_s_ns, RES_PRF_AUTH, file); do_section (pfcode, &handle, ns_s_ar, RES_PRF_ADD, file); if (qdcount == 0 && ancount == 0 && nscount == 0 && arcount == 0) putc('\n', file); }
int DnsResolver_lookupMx(DnsResolver *self, const char *domain, DnsMxResponse **resp) { int query_stat = DnsResolver_query(self, domain, ns_t_mx); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsMxResponse *respobj = (DnsMxResponse *) malloc(sizeof(DnsMxResponse) + msg_count * sizeof(struct mxentry *)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsMxResponse) + msg_count * sizeof(struct mxentry *)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_mx != ns_rr_type(rr)) { continue; } // end if const unsigned char *rdata = ns_rr_rdata(rr); if (ns_rr_rdlen(rr) < NS_INT16SZ) { goto formerr; } // end if int preference = ns_get16(rdata); rdata += NS_INT16SZ; // NOTE: NS_MAXDNAME で十分なのかイマイチ確証が持てないが, bind8 の dig コマンドの実装でもこの値を使っていたのでいいのではないか. char dnamebuf[NS_MAXDNAME]; int dnamelen = ns_name_uncompress(self->msgbuf, self->msgbuf + self->msglen, rdata, dnamebuf, sizeof(dnamebuf)); if (NS_INT16SZ + dnamelen != ns_rr_rdlen(rr)) { goto formerr; } // end if // TODO: dnamebuf は NULL 終端が保証されているのか? size_t domainlen = strlen(dnamebuf); respobj->exchange[respobj->num] = (struct mxentry *) malloc(sizeof(struct mxentry) + sizeof(char[domainlen + 1])); if (NULL == respobj->exchange[respobj->num]) { goto noresource; } // end if respobj->exchange[respobj->num]->preference = preference; if (domainlen + 1 <= strlcpy(respobj->exchange[respobj->num]->domain, dnamebuf, domainlen + 1)) { abort(); } // end if ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsMxResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); noresource: DnsMxResponse_free(respobj); return DnsResolver_setError(self, NETDB_INTERNAL); } // end function : DnsResolver_lookupMx
/* * Print the contents of a query. * This is intended to be primarily a debugging routine. */ void fp_nquery(const u_char *msg, int len, FILE *file) { ns_msg handle; int qdcount, ancount, nscount, arcount; u_int opcode, rcode, id; if ((_res.options & RES_INIT) == 0 && res_init() == -1) return; if (ns_initparse(msg, len, &handle) < 0) { fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); return; } opcode = ns_msg_getflag(handle, ns_f_opcode); rcode = ns_msg_getflag(handle, ns_f_rcode); id = ns_msg_id(handle); qdcount = ns_msg_count(handle, ns_s_qd); ancount = ns_msg_count(handle, ns_s_an); nscount = ns_msg_count(handle, ns_s_ns); arcount = ns_msg_count(handle, ns_s_ar); /* * Print header fields. */ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode) fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", _res_opcodes[opcode], _res_resultcodes[rcode], (int)id); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX)) putc(';', file); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { fprintf(file, "; flags:"); if (ns_msg_getflag(handle, ns_f_qr)) fprintf(file, " qr"); if (ns_msg_getflag(handle, ns_f_aa)) fprintf(file, " aa"); if (ns_msg_getflag(handle, ns_f_tc)) fprintf(file, " tc"); if (ns_msg_getflag(handle, ns_f_rd)) fprintf(file, " rd"); if (ns_msg_getflag(handle, ns_f_ra)) fprintf(file, " ra"); if (ns_msg_getflag(handle, ns_f_z)) fprintf(file, " ??"); if (ns_msg_getflag(handle, ns_f_ad)) fprintf(file, " ad"); if (ns_msg_getflag(handle, ns_f_cd)) fprintf(file, " cd"); } if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { fprintf(file, "; %s: %d", p_section(ns_s_qd, (int)opcode), qdcount); fprintf(file, ", %s: %d", p_section(ns_s_an, (int)opcode), ancount); fprintf(file, ", %s: %d", p_section(ns_s_ns, (int)opcode), nscount); fprintf(file, ", %s: %d", p_section(ns_s_ar, (int)opcode), arcount); } if ((!_res.pfcode) || (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { putc('\n',file); } /* * Print the various sections. */ do_section(&handle, ns_s_qd, RES_PRF_QUES, file); do_section(&handle, ns_s_an, RES_PRF_ANS, file); do_section(&handle, ns_s_ns, RES_PRF_AUTH, file); do_section(&handle, ns_s_ar, RES_PRF_ADD, file); if (qdcount == 0 && ancount == 0 && nscount == 0 && arcount == 0) putc('\n', file); }
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); } } }
/* Simple interface to provide DNS MX record resolution. @param Pointer to the c string hostname you would like resolved to an MX record. @param Pointer to the struct you would like the results written out to. @return Return is of type int and is just the mx family type in the variable ohana. Ohana is hawaiian for family. */ int resolve_server(char * hostname, struct sockaddr_storage * result) { pthread_mutex_lock(&dns_lock); res_init(); int error = 0; int ohana = 0; ns_msg msg; ns_rr rr; struct addrinfo * addr_res; int res_length = 0; unsigned char dns_answer[4096] = {0}; char display_buffer[4096] = {0}; //ldns variables ldns_resolver *ldns_resolv; ldns_rdf *ldns_domain; ldns_pkt *ldns_packet; ldns_rr_list *ldns_mx_records; ldns_status s; //Setup ldns to query for the mx record s = ldns_resolver_new_frm_file(&ldns_resolv, NULL); ldns_domain = ldns_dname_new_frm_str(hostname); //Use ldns to query ldns_packet = ldns_resolver_query(ldns_resolv, ldns_domain, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, LDNS_RD); //parse ldns query results ldns_mx_records = ldns_pkt_rr_list_by_type(ldns_packet, LDNS_RR_TYPE_MX, LDNS_SECTION_ANSWER); //Sort and print mx records ldns_rr_list_sort(ldns_mx_records); ldns_rr_list_print(stdout, ldns_mx_records); for (int i = 0; i < ldns_mx_records->_rr_count; i++) { printf("^_^ i= %d\n", i); printf(">_> %s",ldns_rr2str(ldns_rr_list_rr(ldns_mx_records, i))); printf(">.> %s\n", last_str_split(ldns_rr2str(ldns_rr_list_rr(ldns_mx_records, i)), " ")); } /////////////////Old code below///////////////////// res_length = res_query(hostname, C_IN, T_MX, dns_answer, sizeof(dns_answer)); if (ns_initparse(dns_answer, res_length, &msg)<0) { printf("hostname = %s\n", hostname); printf("res_length = %d\n", res_length); perror("DNS has gone wrong!"); print_to_log("DNS resource query has failed", LOG_ERR); } else { res_length = ns_msg_count(msg, ns_s_an); for (int i = 0; i < res_length; i++) { //printf("DNS loop level = %d\n", i); ns_parserr(&msg, ns_s_an, i, &rr); ns_sprintrr(&msg, &rr, NULL, NULL, display_buffer, sizeof(display_buffer)); if (ns_rr_type(rr) == ns_t_mx) { //String parsing solution for rr. Requires creation of display_buffer above error = getaddrinfo(last_str_split(display_buffer, " "), NULL, NULL, &addr_res); if (error != 0) { printf("error = %d\n", error); printf("display_buffer = %s\n", display_buffer); printf("last_str_split = %s\n", last_str_split(display_buffer, " ")); perror("getaddrinfo"); } if (addr_res->ai_family==AF_INET) { //printf("IPv4 mode is go\n"); struct sockaddr_in* temp_addr = (struct sockaddr_in*)addr_res->ai_addr; memcpy(result, temp_addr, sizeof(*temp_addr)); //printf("ai_addr hostname -> %s\n", inet_ntoa(temp_addr->sin_addr)); ohana = addr_res->ai_family; } else if (addr_res->ai_family==AF_INET6) { //printf("v6 mode engaged\n"); struct sockaddr_in6 * temp_addr = (struct sockaddr_in6 *) addr_res->ai_addr; memcpy(result, temp_addr, sizeof(*temp_addr)); ohana = addr_res->ai_family; } } freeaddrinfo(addr_res); } } pthread_mutex_unlock(&dns_lock); return ohana; }