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"); }
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); }
/* * クエリを投げる. * @return */ static int DnsResolver_query(DnsResolver *self, const char *domain, int rrtype) { self->resolver.res_h_errno = 0; self->resolv_errno = 0; self->resolv_h_errno = NETDB_SUCCESS; self->msglen = res_nquery(&self->resolver, domain, ns_c_in, rrtype, self->msgbuf, NS_MAXMSG); if (0 > self->msglen) { goto queryfail; } // end if if (0 > ns_initparse(self->msgbuf, self->msglen, &self->msghanlde)) { self->resolver.res_h_errno = NO_RECOVERY; goto queryfail; } // end if int rcode_flag = ns_msg_getflag(self->msghanlde, ns_f_rcode); if (rcode_flag != ns_r_noerror) { self->resolver.res_h_errno = DnsResolver_rcode2statcode(rcode_flag); goto queryfail; } // end if return NETDB_SUCCESS; queryfail: return DnsResolver_setError(self, self->resolver.res_h_errno); } // end function : DnsResolver_query
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 void dns_handle_local() { struct sockaddr *src_addr = malloc(sizeof(struct sockaddr)); socklen_t src_addrlen = sizeof(struct sockaddr); uint16_t query_id; ssize_t len; int i; const char *question_hostname; ns_msg msg; len = recvfrom(local_sock, global_buf, BUF_SIZE, 0, src_addr, &src_addrlen); if (len > 0) { if (ns_initparse((const u_char *)global_buf, len, &msg) < 0) { ERR("ns_initparse"); free(src_addr); return; } // parse DNS query id // TODO generate id for each request to avoid conflicts query_id = ns_msg_id(msg); question_hostname = hostname_from_question(msg); LOG("request %s\n", question_hostname); id_addr_t id_addr; id_addr.id = query_id; id_addr.addr = src_addr; id_addr.addrlen = src_addrlen; queue_add(id_addr); for (i = 0; i < dns_servers_len; i++) { if (-1 == sendto(remote_sock, global_buf, len, 0, dns_server_addrs[i].addr, dns_server_addrs[i].addrlen)) ERR("sendto"); } } else ERR("recvfrom"); }
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); }
static JSBool Dns_query(JSContext *cx, unsigned argc, jsval *vp) { char *domain; int32_t type; struct __res_state rs; unsigned char rsp[NS_PACKETSZ]; int rlen; ns_msg hdl; JSObject *robj, *sobj; int i; if (argc < 2) return JS_RetErrno(cx, EINVAL); if (res_ninit(&rs)) return JS_RetError(cx, "res_ninit: %s", hstrerror(h_errno)); if (!JS_ValueToInt32(cx, JS_ARGV(cx, vp)[1], &type)) return JS_RetErrno(cx, EINVAL); if (!(domain = JS_EncodeStringValue(cx, JS_ARGV(cx, vp)[0]))) return JS_RetErrno(cx, EINVAL); rlen = res_nquery(&rs, domain, ns_c_in, type, rsp, sizeof(rsp)); JS_free(cx, domain); if (rlen < 0) { JS_SET_RVAL(cx, vp, INT_TO_JSVAL(h_errno)); return JS_TRUE; } if (ns_initparse(rsp, rlen, &hdl)) return JS_RetError(cx, "ns_initparse: %s", strerror(errno)); robj = JS_NewObject(cx, NULL, NULL, NULL); if (!robj) return JS_RetErrno(cx, ENOMEM); JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(robj)); for (i = 0; i < ARRAY_SIZE(smap); i++) { sobj = JS_NewArrayObject(cx, 0, NULL); if (!sobj) { JS_SET_RVAL(cx, vp, JSVAL_NULL); return JS_RetErrno(cx, ENOMEM); } if (!JS_DefineProperty(cx, robj, smap[i].prop, OBJECT_TO_JSVAL(sobj), NULL, NULL, JSPROP_ENUMERATE)) { JS_SET_RVAL(cx, vp, JSVAL_NULL); return JS_RetErrno(cx, ENOMEM); } if (!parse_section(cx, sobj, &hdl, smap[i].sect)) { JS_SET_RVAL(cx, vp, JSVAL_NULL); return JS_FALSE; } } return JS_TRUE; }
static void dns_handle_remote() { struct sockaddr *src_addr = malloc(sizeof(struct sockaddr)); socklen_t src_len = sizeof(struct sockaddr); uint16_t query_id; ssize_t len; const char *question_hostname; int r; ns_msg msg; len = recvfrom(remote_sock, global_buf, BUF_SIZE, 0, src_addr, &src_len); if (len > 0) { if (ns_initparse((const u_char *)global_buf, len, &msg) < 0) { ERR("ns_initparse"); free(src_addr); return; } // parse DNS query id query_id = ns_msg_id(msg); question_hostname = hostname_from_question(msg); if (question_hostname) { LOG("response %s from %s:%d - ", question_hostname, inet_ntoa(((struct sockaddr_in *)src_addr)->sin_addr), htons(((struct sockaddr_in *)src_addr)->sin_port)); } id_addr_t *id_addr = queue_lookup(query_id); if (id_addr) { id_addr->addr->sa_family = AF_INET; uint16_t ns_old_id = htons(id_addr->old_id); memcpy(global_buf, &ns_old_id, 2); r = should_filter_query(msg, ((struct sockaddr_in *)src_addr)->sin_addr); if (r == 0) { if (verbose) printf("pass\n"); if (-1 == sendto(local_sock, global_buf, len, 0, id_addr->addr, id_addr->addrlen)) ERR("sendto"); } else if (r == -1) { schedule_delay(query_id, global_buf, len, id_addr->addr, id_addr->addrlen); if (verbose) printf("delay\n"); } else { if (verbose) printf("filter\n"); } } else { if (verbose) printf("skip\n"); } free(src_addr); } else ERR("recvfrom"); }
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 get_krb_realm(rdpSettings* settings) { #ifdef WITH_RESOLV char* s; char* queryname; int reslen; unsigned char response[2048]; char ns_realm[2048]; ns_msg handle; ns_rr rr; s = settings->hostname; if (settings->kerberos_realm) return 0; do { queryname = get_dns_queryname(s, NULL); if ((reslen = res_query(queryname, ns_c_in, ns_t_txt, response, sizeof(response)))) { ns_initparse(response, reslen, &handle); ns_parserr(&handle, ns_s_an, 0, &rr); if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr), (char*)ns_realm, sizeof(ns_realm)) < 0) goto end; else settings->kerberos_realm = xstrdup(ns_realm); xfree(queryname); return 0; } end: xfree(queryname); for (;*s != '.' && *s != '\0';s++); if (*s != '\0') s++; } while (*s != '\0'); s = settings->hostname; for (;*s != '.';s++); s++; settings->kerberos_realm = xstrdup(s); #endif return 0; }
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; }
void query_as(char *arg, char *namelisten_addr, char *buf, int buflen) { u_char nsbuf[4096]; ns_msg msg; ns_rr rr; int len; // Set namelisten_addr res_init(); struct in_addr listen_addr_in_addr; if (inet_pton(AF_INET, namelisten_addr, &listen_addr_in_addr) > 0) { _res.nscount = 1; _res.nsaddr_list[0].sin_addr = listen_addr_in_addr; } len = res_query(arg, ns_c_any, ns_t_txt, nsbuf, sizeof(nsbuf)); ns_initparse(nsbuf, len, &msg); ns_parserr(&msg, ns_s_an, 0, &rr); ns_sprintrr(&msg, &rr, NULL, NULL, buf, buflen); }
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 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); }
void dump_dns(const u_char *payload, size_t paylen, FILE *trace, const char *endline) { u_int opcode, rcode, id; const char *sep; ns_msg msg; fprintf(trace, " %sdns ", endline); if (ns_initparse(payload, paylen, &msg) < 0) { fputs(strerror(errno), trace); return; } opcode = ns_msg_getflag(msg, ns_f_opcode); rcode = ns_msg_getflag(msg, ns_f_rcode); id = ns_msg_id(msg); fprintf(trace, "%s,%s,%u", p_opcode(opcode), p_rcode(rcode), id); sep = ","; #define FLAG(t,f) if (ns_msg_getflag(msg, f)) { \ fprintf(trace, "%s%s", sep, t); \ sep = "|"; \ } FLAG("qr", ns_f_qr); FLAG("aa", ns_f_aa); FLAG("tc", ns_f_tc); FLAG("rd", ns_f_rd); FLAG("ra", ns_f_ra); FLAG("z", ns_f_z); FLAG("ad", ns_f_ad); FLAG("cd", ns_f_cd); #undef FLAG dump_dns_sect(&msg, ns_s_qd, trace, endline); dump_dns_sect(&msg, ns_s_an, trace, endline); dump_dns_sect(&msg, ns_s_ns, trace, endline); dump_dns_sect(&msg, ns_s_ar, trace, endline); }
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); } } } }
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"); }
/* ** naptr_resolve() ** Retrieves NAPTR records associated with a given E.164 number on given ** root domains. The root domains will be queried serially in the given ** array order. ** ** Note: This queries for the raw NAPTR record only. It does not do ** the NAPTR looping & rewrite. ** ** Parameters: ** char *e164_number : null terminated E.164 number string (telephone #) ** char **root_domains : pointer to array of root domain strings. ** Setting this to NULL will default to "e164.com". ** NAPTR_record **results : preallocated buffer for results. ** int max_results : size of results buffer (in number of NAPTR_records) ** ** Returns the total number of NAPTR records. */ int naptr_resolve(char *e164_number, char **root_domains, NAPTR_record **results, int max_results) { char *e164; char *e164_fqd; int index; int end_of_array=0; int response_len; int rr_num; int total_records = 0; unsigned char buffer[NS_PACKETSZ]; uint16_t msg_count; ns_msg handle; ns_rr rr; const ns_sect section = ns_s_an; /* We want the answer section */ NAPTR_record **curr_pos = results; /* ** Set to default root domains if null */ if(root_domains==NULL) root_domains=root_domain_defaults; /* ** Clean up E.164 number */ if((e164=reformat_e164(e164_number))==NULL) return 0; /* ** Loop through all given root domains */ for(index=0;!end_of_array && index<MAX_ROOT_DOMAINS;index++) { char *curr_root_domain=*(root_domains+index); if(curr_root_domain==NULL) break; /* ** Convert E.164 number to E.164 fully qualified domain name. */ e164_fqd=format_e164_fqd(NULL,e164,curr_root_domain); /* ** Do the query ** Set the class to Internet & type of query to NAPTR ** (See arpa/nameser.h) ** Note: The 'res_' functions are not thread-safe. */ response_len=res_query(e164_fqd, ns_c_in, ns_t_naptr, buffer, NS_PACKETSZ); free(e164_fqd); if(response_len<0) continue; if(ns_initparse(buffer,response_len, &handle)<0) continue; /* ** Get number of messages */ msg_count=ns_msg_count(handle,section); /* ** Loop through all messages for this root domain */ for(rr_num=0;rr_num<msg_count;rr_num++) { if(ns_parserr(&handle,section,rr_num,&rr)>=0) { /* ** Create an NAPTR_record, insert into results array ** sorted by order and preference. */ NAPTR_record *tmp_rec_p = create_naptr_record(&handle,&rr); if(tmp_rec_p!=NULL) { if(insertion_sort(curr_pos,tmp_rec_p,rr_num,max_results)==0) { end_of_array=1; break; } total_records++; } } } /* ** Update position into array such that any results from next ** root domain query will be appended (that is, don't mix it ** with results from previous root domains). ** Update the remaining space in the results buffer. */ curr_pos = results+total_records; max_results -= rr_num; } free(e164); return total_records; }
int dns_get_mx_list(const char *host, int port, struct mx_hostentry **he, int no_mx) { char outname[MAXDNAME]; ns_msg msg; ns_rr rr; const char *searchhost; const unsigned char *cp; unsigned char *ans; struct mx_hostentry *hosts = NULL; size_t nhosts = 0; size_t anssz; int pref; int cname_recurse; int err; int i; res_init(); searchhost = host; cname_recurse = 0; anssz = 65536; ans = malloc(anssz); if (ans == NULL) return (1); if (no_mx) goto out; repeat: err = res_search(searchhost, ns_c_in, ns_t_mx, ans, anssz); if (err < 0) { switch (h_errno) { case NO_DATA: /* * Host exists, but no MX (or CNAME) entry. * Not an error, use host name instead. */ goto out; case TRY_AGAIN: /* transient error */ goto transerr; case NO_RECOVERY: case HOST_NOT_FOUND: default: errno = ENOENT; goto err; } } if (!ns_initparse(ans, anssz, &msg)) goto transerr; switch (ns_msg_getflag(msg, ns_f_rcode)) { case ns_r_noerror: break; case ns_r_nxdomain: goto err; default: goto transerr; } for (i = 0; i < ns_msg_count(msg, ns_s_an); i++) { if (ns_parserr(&msg, ns_s_an, i, &rr)) goto transerr; cp = ns_rr_rdata(rr); switch (ns_rr_type(rr)) { case ns_t_mx: pref = ns_get16(cp); cp += 2; err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), cp, outname, sizeof(outname)); if (err < 0) goto transerr; add_host(pref, outname, port, &hosts, &nhosts); break; case ns_t_cname: err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), cp, outname, sizeof(outname)); if (err < 0) goto transerr; /* Prevent a CNAME loop */ if (cname_recurse++ > 10) goto err; searchhost = outname; goto repeat; default: break; } } out: err = 0; if (0) { transerr: if (nhosts == 0) err = 1; } if (0) { err: err = -1; } free(ans); if (!err) { /* * If we didn't find any MX, use the hostname instead. */ if (nhosts == 0) add_host(0, searchhost, port, &hosts, &nhosts); qsort(hosts, nhosts, sizeof(*hosts), sort_pref); } if (nhosts > 0) { /* terminate list */ *hosts[nhosts].host = 0; } else { if (hosts != NULL) free(hosts); hosts = NULL; } *he = hosts; return (err); free(ans); if (hosts != NULL) free(hosts); return (err); }
/* Returns 1 with an answer, 0 when reply was old, -1 on fatal errors */ int nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr) { register int msglen, qtype, atype, n, i; register struct nb_dns_entry *ne, *lastne; socklen_t fromlen; struct sockaddr_storage from; u_long msg[MAXPACKET / sizeof(u_long)]; register char *bp, *ep; register char **ap, **hap; register u_int16_t id; register const u_char *rdata; register u_int32_t rttl = 0; // make compiler happy. register struct hostent *he; register size_t rdlen; ns_msg handle; ns_rr rr; /* This comes from the second half of do_query() */ fromlen = sizeof(from); msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0, (struct sockaddr*)&from, &fromlen); if (msglen <= 0) { snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): %s", my_strerror(errno)); return (-1); } if (msglen < HFIXEDSZ) { snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): undersized: %d", msglen); return (-1); } if (ns_initparse((u_char *)msg, msglen, &handle) < 0) { snprintf(errstr, NB_DNS_ERRSIZE, "ns_initparse(): %s", my_strerror(errno)); nr->host_errno = NO_RECOVERY; return (-1); } /* RES_INSECURE1 style check */ if (_nb_dns_cmpsockaddr((struct sockaddr*)&nd->server, (struct sockaddr*)&from, errstr) < 0) { nr->host_errno = NO_RECOVERY; return (-1); } /* Search for this request */ lastne = NULL; id = ns_msg_id(handle); for (ne = nd->list; ne != NULL; ne = ne->next) { if (ne->id == id) break; lastne = ne; } /* Not an answer to a question we care about anymore */ if (ne == NULL) return (0); /* Unlink this entry */ if (lastne == NULL) nd->list = ne->next; else lastne->next = ne->next; ne->next = NULL; /* RES_INSECURE2 style check */ /* XXX not implemented */ /* Initialize result struct */ memset(nr, 0, sizeof(*nr)); nr->cookie = ne->cookie; qtype = ne->qtype; /* Deal with various errors */ switch (ns_msg_getflag(handle, ns_f_rcode)) { case ns_r_nxdomain: nr->host_errno = HOST_NOT_FOUND; free(ne); return (1); case ns_r_servfail: nr->host_errno = TRY_AGAIN; free(ne); return (1); case ns_r_noerror: break; case ns_r_formerr: case ns_r_notimpl: case ns_r_refused: default: nr->host_errno = NO_RECOVERY; free(ne); return (1); } /* Loop through records in packet */ memset(&rr, 0, sizeof(rr)); memset(&nd->dns_hostent, 0, sizeof(nd->dns_hostent)); he = &nd->dns_hostent.hostent; /* XXX no support for aliases */ he->h_aliases = nd->dns_hostent.host_aliases; he->h_addr_list = nd->dns_hostent.h_addr_ptrs; he->h_addrtype = ne->atype; he->h_length = ne->asize; free(ne); bp = nd->dns_hostent.hostbuf; ep = bp + sizeof(nd->dns_hostent.hostbuf); hap = he->h_addr_list; ap = he->h_aliases; for (i = 0; i < ns_msg_count(handle, ns_s_an); i++) { /* Parse next record */ if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) { if (errno != ENODEV) { nr->host_errno = NO_RECOVERY; return (1); } /* All done */ break; } /* Ignore records that don't answer our query (e.g. CNAMEs) */ atype = ns_rr_type(rr); if (atype != qtype) continue; rdata = ns_rr_rdata(rr); rdlen = ns_rr_rdlen(rr); rttl = ns_rr_ttl(rr); switch (atype) { case T_A: case T_AAAA: if (rdlen != (unsigned int) he->h_length) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): bad rdlen %d", (int) rdlen); nr->host_errno = NO_RECOVERY; return (-1); } if (bp + rdlen >= ep) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): overflow 1"); nr->host_errno = NO_RECOVERY; return (-1); } if (nd->dns_hostent.numaddrs + 1 >= MAXADDRS) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): overflow 2"); nr->host_errno = NO_RECOVERY; return (-1); } memcpy(bp, rdata, rdlen); *hap++ = bp; bp += rdlen; ++nd->dns_hostent.numaddrs; /* Keep looking for more A records */ break; case T_TXT: if (bp + rdlen >= ep) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): overflow 1 for txt"); nr->host_errno = NO_RECOVERY; return (-1); } memcpy(bp, rdata, rdlen); he->h_name = bp+1; /* First char is a control character. */ nr->hostent = he; nr->ttl = rttl; return (1); case T_PTR: n = dn_expand((const u_char *)msg, (const u_char *)msg + msglen, rdata, bp, ep - bp); if (n < 0) { /* XXX return -1 here ??? */ nr->host_errno = NO_RECOVERY; return (1); } he->h_name = bp; /* XXX check for overflow */ bp += n; /* returned len includes EOS */ /* "Find first satisfactory answer" */ nr->hostent = he; nr->ttl = rttl; return (1); } } nr->hostent = he; nr->ttl = rttl; return (1); }
// for(int i=0; i<100; i++) { // printf("I won't call perl scripts from 'system' functions!\n"); // } unsigned char* txt_info_for_hostname(const char* domain, int *txt_len, bool decode) { assert(strlen(domain) < 256); FILE *fp; int i=0; char path[100]; std::string real_result; char* result; char* aux_result; char command[325]; // Somewhat arbitrary limit, but txt_len must // be less than 256 characters in size /* Attribution: http://wiki.shellium.org/w/DNS_functions_%28example_program%29 */ unsigned char query_buffer[1024]; ns_msg query_msg; ns_rr query_rr; int query_result = res_query(domain, C_IN, T_TXT, query_buffer, sizeof(query_buffer)); if(query_result == -1) { // TODO: Return an error code or something goto error_ret; } if(ns_initparse(query_buffer, query_result, &query_msg) == -1) { goto error_ret; } for (i = 0; i < ns_msg_count(query_msg, ns_s_an); i++) { if (ns_parserr(&query_msg, ns_s_an, i, &query_rr)) { goto error_ret; } if (ns_rr_type(query_rr) == ns_t_txt) { const unsigned char* data1 = ns_rr_rdata(query_rr); aux_result = (char*) malloc(sizeof(char) * ns_rr_rdlen(query_rr)); memcpy(aux_result, data1, ns_rr_rdlen(query_rr)); if(!aux_result) { goto error_ret; } printf("NS_TXT!\n"); //printf("%s", (const char*)data1); //printf("\n"); print_buffer((const char*)data1, ns_rr_rdlen(query_rr) + 32); //printf("ENDOFTEXT\n"); } } if(decode) { sprintf(command, "nslookup %s | ./extract_and_decode.pl", domain); } else { sprintf(command, "nslookup %s | ./extract.pl", domain); } /* Open the command for reading. */ fp = popen(command, "r"); if (fp == NULL) { return NULL; } /* Read the output a line at a time - output it. */ while (fgets(path, sizeof(path)-1, fp) != NULL) { real_result += path; } /* close */ pclose(fp); result = (char *)malloc(sizeof(char) * (real_result.length() + 1)); if(!result) { return NULL; } strcpy(result, real_result.c_str()); *txt_len = real_result.length(); print_buffer(result, *txt_len); print_buffer(aux_result, query_result); return (unsigned char*)result; error_ret: *txt_len = 0; return NULL; }
int dns_query_afsdb(key_serial_t key, const char *cell, char *options) { int ret; char *vllist[MAX_VLS]; /* list of name servers */ int vlsnum = 0; /* number of name servers in list */ unsigned mask = INET_ALL; int response_len; /* buffer length */ ns_msg handle; /* handle for response message */ unsigned long ttl = ULONG_MAX; union { HEADER hdr; u_char buf[NS_PACKETSZ]; } response; /* response buffers */ debug("Get AFSDB RR for cell name:'%s', options:'%s'", cell, options); /* query the dns for an AFSDB resource record */ response_len = res_query(cell, ns_c_in, ns_t_afsdb, response.buf, sizeof(response)); if (response_len < 0) /* negative result */ nsError(h_errno, cell); if (ns_initparse(response.buf, response_len, &handle) < 0) error("ns_initparse: %m"); /* Is the IP address family limited? */ if (strcmp(options, "ipv4") == 0) mask = INET_IP4_ONLY; else if (strcmp(options, "ipv6") == 0) mask = INET_IP6_ONLY; /* look up the hostnames we've obtained to get the actual addresses */ afsdb_hosts_to_addrs(vllist, &vlsnum, handle, ns_s_an, mask, &ttl); info("DNS query AFSDB RR results:%u ttl:%lu", payload_index, ttl); /* set the key's expiry time from the minimum TTL encountered */ if (!debug_mode) { ret = keyctl_set_timeout(key, ttl); if (ret == -1) error("%s: keyctl_set_timeout: %m", __func__); } /* handle a lack of results */ if (payload_index == 0) nsError(NO_DATA, cell); /* must include a NUL char at the end of the payload */ payload[payload_index].iov_base = ""; payload[payload_index++].iov_len = 1; dump_payload(); /* load the key with data key */ if (!debug_mode) { ret = keyctl_instantiate_iov(key, payload, payload_index, 0); if (ret == -1) error("%s: keyctl_instantiate: %m", __func__); } exit(0); }
/* 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; }
/* * Test the case of a SRV record query where the * fake hosts file entry is minimal in the sense * that it omits the priority and weight entries. * The server then fills in some default values. */ static void test_res_fake_srv_query_minimal(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]; 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, "_krb5._tcp.cwrap.org", ns_c_in, ns_t_srv, answer, sizeof(answer)); assert_in_range(rv, 1, 256); 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, 100); assert_int_equal(port, 88); assert_string_equal(hostname, "krb5.cwrap.org"); /* The additional section contains the A record of krb5.cwrap.org */ assert_int_equal(ns_msg_count(handle, ns_s_ar), 1); assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_string_equal(ns_rr_name(rr), "krb5.cwrap.org"); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.23"); }
/* * 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); }
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); }
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"); }
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); } } }
/* * 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); }